想象一下DataGrid的一个DataGrid,它的ItemsSource
设置为ObservableCollection
。此集合为DataGrid
中的每一行提供了查看模型。视图模型反过来提供一行中显示的数据和可能更改此数据的命令。此外,我在DataGrid
的RowValidationRules
属性中添加了一条规则。如果我输入无效数据,此验证规则正常工作。验证基础数据更改时的行
但是,如果通过视图模型提供的命令将无效数据更改为有效数据,则只有当DataGrid
中的当前行失去焦点时,才会再次触发行验证规则。因此,显示的数据可能实际上是有效的,但DataGrid
仍显示一个红色感叹号,表明它具有无效数据。在当前行失去焦点或我再次输入有效数据之前,情况依然如此。
如何强制对当前行进行第二次验证?我已经设置了ValidatesOnTargetUpdated="True"
但这并没有解决问题。我也实现了INotifyPropertyChanged接口,但这也没有解决问题。
解决方案
随着用户mm8指出,INotifyDataErrorInfo
是去的方法。我删除了行验证规则,并在我的视图模型中公开了名为HasErros
的属性,该属性代理了我的模型的HasErrors
属性,该属性依次执行INotifyDataErrorInfo
。接下来,我添加了一个自定义的RowValidationErrorTemplate
<DataGrid.RowValidationErrorTemplate>
<ControlTemplate>
<Grid>
<Ellipse Width="12" Height="12" Fill="Red"/>
<Label Content="!" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"
Foreground="White" FontSize="11"/>
</Grid>
</ControlTemplate>
</DataGrid.RowValidationErrorTemplate>
,并创建以下的自定义样式DataGridRowHeader
<Style x:Key="MyDataGridRowHeaderStyle" TargetType="{x:Type DataGridRowHeader}">
<!-- ... -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridRowHeader}">
<Border>
<Grid>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
<Control SnapsToDevicePixels="True"
Template="{Binding ValidationErrorTemplate, RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}}"
Visibility="{Binding Path=HasErrors, UpdateSourceTrigger=PropertyChanged, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}"/>
</Grid>
</Border>
<!-- ... -->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
注Visibility
的结合。 HasErrors
属性是我上面提到的代理属性。
最后,使用该样式在DataGrid
如下
<DataGrid RowHeaderStyle="{StaticResource MyDataGridRowHeaderStyle}"
...
的BoolToVisibilityConverter
的实现可以发现here。