C# WPF ValidationErrorTemplate样式动态位置
因此,我为每个控件和ValidationErrorTemplate都提供了一个巨大的样式模板字典。问题是,当控件上方没有位置时,我们应该在控件下方显示验证错误。基本上用于窗口顶部的控件。对于窗口底部的控件,验证应显示在控件上方 由于它是一个定义了所有样式的资源字典,因此没有代码隐藏,也没有数据绑定 一个想法是确定C# WPF ValidationErrorTemplate样式动态位置,c#,wpf,validation,controltemplate,resourcedictionary,C#,Wpf,Validation,Controltemplate,Resourcedictionary,因此,我为每个控件和ValidationErrorTemplate都提供了一个巨大的样式模板字典。问题是,当控件上方没有位置时,我们应该在控件下方显示验证错误。基本上用于窗口顶部的控件。对于窗口底部的控件,验证应显示在控件上方 由于它是一个定义了所有样式的资源字典,因此没有代码隐藏,也没有数据绑定 一个想法是确定装饰元素占位符的位置并分别隐藏/显示模板。但在XAML中,我还没有找到任何解决方案 <ControlTemplate x:Key="ValidationErrorTempl
装饰元素占位符的位置并分别隐藏/显示模板。但在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=“?”应为0或1,具体取决于控件的顶部 有两个单独的模板(一个相反),一个用于顶部的项目,另一个用于底部的项目,只要对象包含您所说的控件,就可以认为它们是合适的。因此我终于找到了解决方案:attached property。我在AdornerDecorator.Loaded事件上订阅的属性更改回调方法上创建了一个attach属性和。在该方法中,您可以检查实际位置,并根据需要更改属性
[示例代码片段,在真实源代码中,由于特定于代码的问题,它更容易外包和重新检查]
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
事件来确保渲染位置将为您提供实际位置,而不是其他位置(例如零或某些相对位置)
最后,您需要将附加属性附加到XAML中的装饰器:
<AdornerDecorator Behaviors:AdornerPositionCalculator.AllowDynamicPosition="True">
<!-- custom style here -->
</AdornerDecorator>
听起来不错,但我们不想为每个带有键的控件定义明确的样式。特别是,因为我们开发了一个框架,所以不能保证他们不会忘记添加正确的样式键。您是否考虑过使用DataTrigger根据AdorneDeletePlaceholder的值设置Grid.Row?我以前从未尝试过这种方法,但我认为它会按照你描述的方式工作。