我正在使用 INotifyDataErrorInfo 来触发验证。
我无法从 Validation.ErrorTemplate 中获得控件。我需要堆栈面板的实际高度,以将该高度添加到装饰元素的底部边距,以便错误将显示在装饰元素下方,并且下面的任何控件都将向下移动。
我曾尝试在转换器内使用可视化树,但没有任何反应。我也尝试过使用 XAML 仍然没有。
<converters:ErrorsToMarginMultiConverter x:Key="ErrorsToMarginMultiConverter"/>
<Style TargetType="{x:Type Control}" x:Key="ValidationStyle">
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="Height" Value="25"/>
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<StackPanel>
<!--The Original Control-->
<AdornedElementPlaceholder x:Name="OriginalControl"/>
<!--The Errors List-->
<ItemsControl ItemsSource="{Binding}" x:Name="ErrorItemsControl">
<ItemsControl.ItemTemplate>
<DataTemplate>
<BulletDecorator Width="{Binding ElementName=OriginalControl, Path=ActualWidth, UpdateSourceTrigger=PropertyChanged}">
<BulletDecorator.Bullet>
<Ellipse Fill="Red" Width="5" Height="5"/>
</BulletDecorator.Bullet>
<TextBlock Text="{Binding ErrorContent, StringFormat=' {0}'}" Foreground="Red" TextWrapping="Wrap"/>
</BulletDecorator>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="BorderThickness" Value="2" />
<Setter Property="BorderBrush" Value="DarkRed" />
<Setter Property="Margin">
<Setter.Value>
<MultiBinding Converter="{StaticResource ErrorsToMarginMultiConverter}" UpdateSourceTrigger="PropertyChanged">
<Binding Path="(Validation.Errors)" RelativeSource="{RelativeSource Self}"/>
<Binding RelativeSource="{RelativeSource Self}"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
我希望以某种方式获得验证错误模板中的控件作为我的转换器的参数,或者使用转换器内部的代码获取它们以提取它们的实际高度。
我想获取该堆栈面板的高度,以便将其作为底部边距添加到原始控件(TextBox),以在出现验证错误时实现预期结果。 树视图 转换器代码示例
编辑:我设法找到了部分解决方案,
public object Convert(object[] value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null)
{
var adornedElement = value[1] as Control;
var adornerLayer = System.Windows.Documents.AdornerLayer.GetAdornerLayer(adornedElement);
var templatedAdorner = adornerLayer.GetAdorners(adornedElement);
var margin = adornedElement.Margin;
margin.Bottom = 20;
if (templatedAdorner != null && templatedAdorner.Length > 0)
margin.Bottom = templatedAdorner[0].ActualHeight;
return margin;
}
return value;
}
现在的问题是这个转换器被触发了两次,第一次是清除以前的验证错误,第二次是我添加错误。它第一次找到 templatedAdorner 并读取它的实际高度。但是第二次如果找到装饰层但不存在templatedAdorned(null)。在我的视觉树中,我可以看到它们。此外,验证错误计数也不正确,尽管它们在视图中正确显示。
触发器是 ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName)); 来自 INotifyDataErrorInfo。