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

标签 wpf validation templates mvvm

我目前正在使用 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/

相关文章:

c# - 在图像查看和编辑 WPF 上共享冲突

java - 日期程序的验证问题

c++ - 构造函数上的模板和隐式转换预防

django - 如何模仿django admin的OneToOneField可选表单

wpf - 是否有一组接口(interface)可以实现以避免在 WPF 绑定(bind)中有转换器

c# - 加快 WPF 调整大小/重绘

c# - 使用 Action<> 和 Func<> 的命令

php - 文件路径的正则表达式

validation - 本地验证travis.yml文件

c++ - 使用模板在 C++ 中进行转换