WPF ValidationErrorTemplate样式的动态位置
本文关键字:动态 位置 样式 ValidationErrorTemplate WPF | 更新日期: 2023-09-27 18:20:39
因此,我为每个控件和ValidationErrorTemplate都获得了一个巨大的样式模板字典。问题是,当控件上方没有位置时,我们应该在控件下方显示验证错误。基本用于窗口顶部的控件。对于窗口底部的控件,验证应显示在控件上方。
由于它是一个定义了所有样式的资源字典,因此没有代码隐藏,而且也不可能有数据绑定。
一个想法是确定AdornedElementPlaceholder
的位置并分别隐藏/显示模板。但我在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>
网格。Row="???"应为0或1,具体取决于控件的顶部。
有两个独立的模板(一个与另一个相对),并将一个用于顶部的项目,另一个用于底部的项目,无论哪个对象包含您所说的控件,都会认为合适。
所以我终于找到了解决方案:附加属性。我创建了一个附加属性,并在属性更改回调方法上订阅了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>