我目前正在使用 WPF 验证开发 MVVM 解决方案。
我想要做的是能够在我的上下文中使用“ShowErrors”可见性属性来控制何时显示验证装饰器。
我有以下 WPF ComboBox 验证装饰器模板,包含在我的 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 绑定(bind)到的 UserControl 的 x:Name 为“MainContext”
我发现了一些建议;
Visibility="{Binding DataContext.ShowErrors, Source={x:Reference Name=MainContext}, Mode=TwoWay}">
这给出了错误
Unresolved reference 'MainContext'
还有;
Visibility="{Binding DataContext.ShowErrors, ElementName=MainContext, Mode=TwoWay}">
这根本行不通。
Edit2:如果我将整个装饰器从 Appliation.xaml 中移出并移入 UserControl 资源中,则使用;
Visibility="{Binding DataContext.ShowErrors, ElementName=MainContext, Mode=TwoWay}">
它有效......但并不理想,因为我不想在所有屏幕上重复模板
编辑 3: 好的,我现在找到了解决方法。我使用以下内容进行可见性绑定(bind)...
Visibility="{Binding ElementName=customAdorner1, Path=AdornedElement.Parent.DataContext.ShowErrors, Converter={StaticResource MyBolVisibilityConverter}, Mode=TwoWay}"
然后,我向上下文添加了一个 bool ShowErrors 属性,并添加了一个转换器来将 bool 值转换为可见性值,这主要是因为 ShowErrors 属性实际结束的位置。
这有点令人困惑,因为我的表单是一个主详细信息安排,其中装饰器显示在详细信息部分中,该部分有自己的 DataContext。当然,这无法直接访问 UserControl 的 DataContext。
这对我来说确实有点像黑客,所以我希望有更好的解决方案!
最佳答案
我通过向我的 DataContext 添加 ShowErrors
bool 属性,然后将 Adorner 可见性绑定(bind)到 AdornedElement 的父级 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 即可显示或隐藏装饰器。
这非常有用,因为装饰器总是出现在最顶层,因此显示在自定义对话框等的顶部。
关于WPF 绑定(bind) MVVM 中验证装饰器的可见性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13894233/