C# MVVM模式、IDataErrorInfo和绑定到显示错误?
上面有一篇关于MVVM的好文章,他们将Xaml中的验证错误绑定到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
validation.ErrorTemplate=“{x:Null}”
。我不明白为什么以及如何从IDataErrorInfo中显示错误?任何人都可以告诉我如何使用MVVM方法将错误消息显示在屏幕上?我猜这就是验证。ErrorTemplate=“{x:Null}”在出现错误时删除红色矩形。这可能被设置为在表单启动时文本框周围不能有红色矩形
对于表单显示的错误,我在代码中看到了:Content=“{Binding ElementName=lastNameTxt,Path=(Validation.Errors).CurrentItem}”
,因此,我仍然猜测它绑定到文本框(而不是数据模型)并检查静态验证是否存在错误。是否存在可能从数据模型连接到IDataErrorInfo的错误
我猜对了吗?几分钟前我还在看同一个样品。你猜对了。在这个代码示例中,他们从TextBox控件中删除了默认的ErrorTemplate,这样它就不会显示红色矩形。他们不使用ErrorTemplate,而是创建内容绑定到特定文本框的验证错误的ContentProvider。当您绑定到支持IDataErrorInfo的对象时,WPF绑定类有几个功能需要考虑:
<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>
}<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;
}
}