0

So, I got a huge style template dictionary for every control and for ValidationErrorTemplate as well. The problem is, that we should show validation error below the control when there is no place above the control. Basicly for controls at the top of the window. For controls at the bottom of the window the validation should be shown above the control.

Since it a resource dictionary where every styles are defined there is no code-behind and also no data binding is possible.

One idea would be to determine the AdornedElementPlaceholder's position and hide / show the template respectivly. But I haven't find any solution to do that in XAML.

    <ControlTemplate x:Key="ValidationErrorTemplate">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <Grid Grid.Row="1">
                <Border>
                    <AdornedElementPlaceholder />
                </Border>                
            </Grid>
            <AdornerDecorator Grid.Row="????">
                <Border >
                    <!-- some style comes here ...  -->
                </Border>
            </AdornerDecorator>
        </Grid>
    </ControlTemplate>

Grid.Row="????" should be either 0 or 1, depending on the top of the control.

4

2 回答 2

0

有两个单独的模板(一个与另一个相反),一个用于顶部的项目,一个用于底部的项目,只要包含您所说的控件的任何对象都认为合适。

于 2013-07-01T15:24:42.670 回答
0

所以我终于找到了解决方案:附加属性。我创建了一个附加属性,并在 AdornerDecorator.Loaded 事件上订阅的属性更改回调方法上。在该方法中,您可以检查实际位置并根据需要更改属性。

[示例代码片段,在真实源代码中,由于代码特定问题,它更加外包和重新检查]

private static void DecoratorLoaded(object obj, RoutedEventArgs e)
{
     var decorator = obj as Decorator;
     if (decorator != null && decorator.IsVisible)
     {
        // get the position
        Point renderedLocation = decorator.TranslatePoint(new Point(0, 0), Application.Current.MainWindow);
        if (renderedLocation != new Point(0, 0))
        {
           // check width
           var maxAllowedWidth = Application.Current.MainWindow.ActualWidth - renderedLocation.X - 40;               
           decorator.SetValue(FrameworkElement.MaxWidthProperty, maxAllowedWidth);

           // check place above the control
           var isEnoughPlaceAbove = renderedLocation.Y > decorator.ActualHeight + 10;
           decorator.SetValue(Grid.RowProperty, isEnoughPlaceAbove ? 0 : 2);

           // invalidate to re-render
           decorator.InvalidateVisual();               
        }
     }
}

您需要使用Loaded事件来确保 renderLocation 将为您提供实际位置而不是其他东西(例如零或一些相对位置)。

最后,您需要将附加属性附加到 XAML 中的装饰器:

<AdornerDecorator Behaviors:AdornerPositionCalculator.AllowDynamicPosition="True">
  <!-- custom style here -->
</AdornerDecorator>
于 2013-07-09T13:35:10.500 回答