Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# MVVM模式、IDataErrorInfo和绑定到显示错误?_C#_.net_Wpf_Mvvm_Binding - Fatal编程技术网

C# MVVM模式、IDataErrorInfo和绑定到显示错误?

C# MVVM模式、IDataErrorInfo和绑定到显示错误?,c#,.net,wpf,mvvm,binding,C#,.net,Wpf,Mvvm,Binding,上面有一篇关于MVVM的好文章,他们将Xaml中的验证错误绑定到validation.ErrorTemplate=“{x:Null}”。我不明白为什么以及如何从IDataErrorInfo中显示错误?任何人都可以告诉我如何使用MVVM方法将错误消息显示在屏幕上?我猜这就是验证。ErrorTemplate=“{x:Null}”在出现错误时删除红色矩形。这可能被设置为在表单启动时文本框周围不能有红色矩形 对于表单显示的错误,我在代码中看到了:Content=“{Binding ElementName

上面有一篇关于MVVM的好文章,他们将Xaml中的验证错误绑定到
validation.ErrorTemplate=“{x:Null}”
。我不明白为什么以及如何从IDataErrorInfo中显示错误?任何人都可以告诉我如何使用MVVM方法将错误消息显示在屏幕上?

我猜这就是验证。ErrorTemplate=“{x:Null}”在出现错误时删除红色矩形。这可能被设置为在表单启动时文本框周围不能有红色矩形

对于表单显示的错误,我在代码中看到了:
Content=“{Binding ElementName=lastNameTxt,Path=(Validation.Errors).CurrentItem}”
,因此,我仍然猜测它绑定到文本框(而不是数据模型)并检查静态验证是否存在错误。是否存在可能从数据模型连接到IDataErrorInfo的错误


我猜对了吗?

几分钟前我还在看同一个样品。你猜对了。在这个代码示例中,他们从TextBox控件中删除了默认的ErrorTemplate,这样它就不会显示红色矩形。他们不使用ErrorTemplate,而是创建内容绑定到特定文本框的验证错误的ContentProvider。

当您绑定到支持IDataErrorInfo的对象时,WPF绑定类有几个功能需要考虑:

  • ValidateSondaErrors必须为True。这指示WPF在底层对象上查找并使用IDataError接口

  • 如果源对象的IDataError接口报告验证问题,则目标对象上附加的属性Validation.HasError将设置为true。然后,您可以将此属性与触发器一起使用,以更改控件的工具提示,以显示验证错误消息(我在当前项目中执行此操作,最终用户非常喜欢它)

  • Validation.Errors attached属性将包含上次验证尝试导致的任何ValidationResult错误的枚举。如果使用工具提示方法,请使用IValueConverter仅检索第一项。。。否则,在显示错误消息本身时会遇到绑定错误

  • binding类公开NotifyOnValidationError,如果为True,则每次验证规则的状态更改时,都会导致路由事件从绑定控件冒泡出来。如果您希望在绑定控件的容器中实现事件处理程序,然后在列表框中添加和删除验证消息,这将非常有用

  • MSDN上有两种类型的反馈(工具提示和列表框)的示例,但我将粘贴在我在DataGridCells和TextBox上实现工具提示反馈的代码下面

    DataGridCell样式:

       <Style TargetType="{x:Type dg:DataGridCell}"
               x:Key="DataGridCellStyle">
    
          <Setter Property="ToolTip"
                  Value="{Binding Path=Column.(ToolTipService.ToolTip),RelativeSource={RelativeSource Self}}" />
    
          <Style.Triggers>
            <Trigger Property="Validation.HasError"
                     Value="True">
              <Setter Property="ToolTip"
                      Value="{Binding RelativeSource={RelativeSource Self},Path=(Validation.Errors), Converter={StaticResource ErrorContentConverter}}" />
            </Trigger>
          </Style.Triggers>
    
        </Style>
    
    
    
    文本框样式:

         <Style x:Key="ValidatableTextBoxStyle" TargetType="TextBox">
      <!--When the control is not in error, set the tooltip to match the AutomationProperties.HelpText attached property-->
      <Setter Property="ToolTip"
              Value="{Binding RelativeSource={RelativeSource Mode=Self},Path=(AutomationProperties.HelpText)}" />
    
              <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="true">
                  <Setter Property="ToolTip"
                          Value="{Binding RelativeSource={x:Static RelativeSource.Self},Path=(Validation.Errors)[0].ErrorContent}" />
                </Trigger>
              </Style.Triggers>
            </Style>
    
    
    
    ErrorContentConverter(用于检索工具提示的第一条验证错误消息):

    导入System.Collections.ObjectModel
    名称空间转换器
    _
    公共类ErrorContentConverter
    实现IValueConverter
    公共函数转换(ByVal值作为对象,ByVal targetType作为系统.Type,ByVal参数作为对象,ByVal区域性作为系统.Globalization.CultureInfo)作为对象实现System.Windows.Data.IValueConverter.Convert
    将错误调整为ReadOnlyObservableCollection(属于ValidationError)=TryCast(值,ReadOnlyObservableCollection(属于ValidationError))
    如果错误不是什么,那么
    如果错误。计数>0,则
    返回错误(0)。错误内容
    如果结束
    如果结束
    返回字符串。空
    端函数
    作为对象的公共函数ConvertBack(ByVal值作为对象,ByVal targetType作为系统.Type,ByVal参数作为对象,ByVal区域性作为系统.Globalization.CultureInfo)实现System.Windows.Data.IValueConverter.ConvertBack
    抛出新的NotImplementedException()
    端函数
    末级
    结束命名空间
    
    …最后是在文本框中使用样式的示例:

        <TextBox Text="{Binding Path=EstimatedUnits,ValidatesOnDataErrors=True,NotifyOnValidationError=True}"
                 Style="{StaticResource ValidatableTextBoxStyle}"
                 AutomationProperties.HelpText="The number of units which are likely to sell in 1 year." />
    

    这是我用来在工具提示中显示错误或在控件旁边显示小气泡的代码

  • 定义样式

    <Style x:Key="TextBoxValidationStyle" TargetType="{x:Type TextBox}">
        <Style.Triggers>
            <Trigger Property="Validation.HasError" Value="true">
                <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self},  Path=(Validation.Errors)[0].ErrorContent}"/>
            </Trigger>
        </Style.Triggers>
    </Style>
    
    <Style x:Key="TextboxErrorBubbleStyle" TargetType="{x:Type TextBox}" BasedOn="{StaticResource ResourceKey=TextBoxValidationStyle}">
        <Setter Property="Validation.ErrorTemplate">
            <Setter.Value>
                <ControlTemplate>
                    <DockPanel LastChildFill="true">
    
                        <Border Background="Red" DockPanel.Dock="right" Margin="5,0,0,0" Width="10" Height="10" CornerRadius="10"
                            ToolTip="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
    
                            <TextBlock Text="!" VerticalAlignment="center" HorizontalAlignment="center" FontWeight="Bold" Foreground="white"/>
                        </Border>
    
                        <AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center" >
                            <Border BorderBrush="red" BorderThickness="1" />
                        </AdornedElementPlaceholder>
    
                    </DockPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    

    }

  • UI外观和感觉

  • <Style x:Key="TextBoxValidationStyle" TargetType="{x:Type TextBox}">
        <Style.Triggers>
            <Trigger Property="Validation.HasError" Value="true">
                <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self},  Path=(Validation.Errors)[0].ErrorContent}"/>
            </Trigger>
        </Style.Triggers>
    </Style>
    
    <Style x:Key="TextboxErrorBubbleStyle" TargetType="{x:Type TextBox}" BasedOn="{StaticResource ResourceKey=TextBoxValidationStyle}">
        <Setter Property="Validation.ErrorTemplate">
            <Setter.Value>
                <ControlTemplate>
                    <DockPanel LastChildFill="true">
    
                        <Border Background="Red" DockPanel.Dock="right" Margin="5,0,0,0" Width="10" Height="10" CornerRadius="10"
                            ToolTip="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
    
                            <TextBlock Text="!" VerticalAlignment="center" HorizontalAlignment="center" FontWeight="Bold" Foreground="white"/>
                        </Border>
    
                        <AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center" >
                            <Border BorderBrush="red" BorderThickness="1" />
                        </AdornedElementPlaceholder>
    
                    </DockPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    
    <TextBox Text="{Binding Path=FirstName, Mode=TwoWay, ValidatesOnDataErrors=True,NotifyOnValidationError=True, UpdateSourceTrigger=PropertyChanged}"
                Style="{StaticResource TextBoxValidationStyle}" Width="100" Margin="3 5 3 5"/>
     <TextBox Text="{Binding Path=LastName, Mode=TwoWay, ValidatesOnDataErrors=True,NotifyOnValidationError=True, UpdateSourceTrigger=PropertyChanged}"
                Style="{StaticResource TextboxErrorBubbleStyle}" Width="100" Margin="0 5 3 5"/>
    
    public string FirstName
    {
        get { return firstName; }
        set
        {
            if (firstName != value)
            {
                firstName = value;
                RaisePropertyChanged("FirstName");
            }
        }
    }
    
    public string LastName
    {
        get { return lastName; }
        set
        {
            if (lastName != value)
            {
                lastName = value;
                RaisePropertyChanged("LastName");
            }
        }
    }
    public string Error
    {
        get { throw new System.NotImplementedException(); }
    }
    
    public string this[string columnName]
    {
        get
        {
            string message = null;
            if (columnName == "FirstName" && string.IsNullOrEmpty(FirstName))
            {
                message = "Please enter FirstName";
            }
            if (columnName == "LastName" && string.IsNullOrEmpty(LastName))
            {
                message = "Please enter LastName";
            }
            return message;
        }
    }