MVVM中验证装饰器的WPF绑定可见性



我目前正在使用WPF验证开发MVVM解决方案。

我想做的是能够控制验证装饰器何时在我的上下文中使用"ShowErrors"Visibility属性显示。

我有下面的WPF组合框验证装饰模板,包含在我的Application.xaml文件中;

<Style TargetType="{x:Type ComboBox}">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="0,2,40,2" />
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="true">
<Border Background="Red" DockPanel.Dock="right" Margin="5,0,0,0" Width="20" Height="20" CornerRadius="10"
ToolTip="{Binding ElementName=customAdorner1, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
<TextBlock Text="!" VerticalAlignment="center" HorizontalAlignment="center" FontWeight="Bold" Foreground="white">
</TextBlock>
</Border>
<AdornedElementPlaceholder Name="customAdorner1" VerticalAlignment="Center" >
<Border BorderBrush="red" BorderThickness="1" />
</AdornedElementPlaceholder>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

(我有一个单独的文本框模板)

在StackOverflow和Google上进行了一些搜索后,我尝试将以下内容添加到DockPanel中;

Visibility="{Binding DataContext.ShowErrors, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Mode=TwoWay}"

但这似乎对我不起作用,即使同样的方法在主XAML中也能很好地工作。。。。有什么想法吗?

编辑:我将DataContext绑定到的UserControl的x:Name为"MainContext">

我找到了一对建议;

Visibility="{Binding DataContext.ShowErrors, Source={x:Reference Name=MainContext}, Mode=TwoWay}">

这给出了的错误

未解析的引用'MainContext'

以及;

Visibility="{Binding DataContext.ShowErrors, ElementName=MainContext, Mode=TwoWay}">

这根本不起作用。

Edit2:如果我将整个装饰器从Appliation.xaml移到UserControl资源中,那么使用;

Visibility="{Binding DataContext.ShowErrors, ElementName=MainContext, Mode=TwoWay}">

它有效。。。不过并不理想,因为我不想在所有的屏幕上重复模板

编辑3:好的,所以我现在找到了一个解决方法。我将以下内容用于可见性绑定。。。

Visibility="{Binding ElementName=customAdorner1, Path=AdornedElement.Parent.DataContext.ShowErrors, Converter={StaticResource MyBolVisibilityConverter}, Mode=TwoWay}"

然后,我在上下文中添加了一个Boolean ShowErrors属性,并添加了一个把布尔值转换为可见性值的Converter,这主要是因为ShowErrors特性的实际结束位置。

这有点令人困惑,因为我的Form是一个Master Details安排,其中Adorners显示在Details部分,该部分有自己的DataContext。当然,这并不能直接访问UserControl的DataContext。

这对我来说真的有点像黑客,所以我很感激有更好的解决方案!

我通过将ShowErrors布尔属性添加到我的DataContext中,然后将Adorner Visibility绑定到AdornedElement的Parents DataContext来解决这个问题,当然,如果我已知的DataContext。

我在Application.XAML文件中使用了以下XAML;

<Converters:BolVisibilityConverter x:Key="MyBolVisibilityConverter"/>
<Style TargetType="{x:Type TextBox}">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="0,2,40,2" />
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="true" Visibility="{Binding ElementName=customAdorner, Path=AdornedElement.Parent.DataContext.ShowErrors, Converter={StaticResource MyBolVisibilityConverter}, Mode=TwoWay}">
<Border Background="Red" DockPanel.Dock="right" Margin="5,0,0,0" Width="20" Height="20" CornerRadius="10"
ToolTip="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
<TextBlock Text="!" VerticalAlignment="center" HorizontalAlignment="center" FontWeight="Bold" Foreground="white">
</TextBlock>
</Border>
<AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center" >
<Border BorderBrush="red" BorderThickness="1" />
</AdornedElementPlaceholder>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

我使用了以下转换器代码;

Namespace Converters
Public Class BolVisibilityConverter
Implements IValueConverter
Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IValueConverter.Convert
If value Is Nothing OrElse value = False Then
Return Visibility.Hidden
Else
Return Visibility.Visible
End If
End Function
Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack
Return DirectCast(value, Boolean)
End Function
End Class
End Namespace

然后,我只需将DataContext中的ShowErrors属性设置为True或False,即可显示或隐藏Adorners。

这非常有用,因为Adorners总是出现在最顶层,因此显示在自定义对话框等的顶部。

最新更新