【发布时间】:2017-07-17 12:06:51
【问题描述】:
想象一个将ItemsSource 设置为ObservableCollection 的DataGrid。该集合为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 找到。
【问题讨论】:
标签: wpf wpfdatagrid