基础数据更改时验证行 [英] Validate row when underlying data changes
问题描述
想象一下一个DataGrid,它的 ItemsSource
设置为 ObservableCollection
.该集合为 DataGrid
中的每一行提供一个视图模型.视图模型又提供一行显示的数据以及可以更改此数据的命令.另外,我向 DataGrid
的 RowValidationRules
属性添加了一条规则.如果我输入的数据无效,此验证规则会很好地工作.
Imagine a DataGrid with its ItemsSource
set to an ObservableCollection
. This collection provides a view model for each row in the DataGrid
. The view model in turn provides the data that is displayed in one row and a command that may change this data. Additionally, I added a rule to the RowValidationRules
property of DataGrid
. This validation rule works fine in case I enter invalid data.
但是,如果我通过视图模型提供的命令将无效数据更改为有效数据,则仅当 DataGrid
中的当前行失去焦点时,才会再次触发行验证规则.因此,显示的数据实际上可能是有效的,但是 DataGrid
仍然显示红色的感叹号,表明它具有无效的数据.在当前行失去焦点或再次输入有效数据之前,情况一直如此.
However, if I change the invalid data to valid data via the command the view model provides, the row validation rule only gets triggered again if the current row in DataGrid
loses focus. Hence, the displayed data may be actually valid, but the DataGrid
still displays a red exclamation mark showing it has invalid data. This remains the case until the current row loses focus or I enter valid data again.
如何强制对当前行进行第二次验证?我已经设置了 ValidatesOnTargetUpdated ="True"
,但这不能解决问题.我还实现了INotifyPropertyChanged接口,但这也不能解决问题.
How do I force a second validation of the current row? I already set ValidatesOnTargetUpdated="True"
but this didn't solve the problem. I also have implemented the INotifyPropertyChanged interface but this also didn't fix the problem.
解决方案
正如用户 mm8 指出的那样, INotifyDataErrorInfo
是可行的方法.我删除了行验证规则,并在视图模型中暴露了名为 HasErros
的属性,该属性替代了模型的 HasErrors
属性,该属性又实现了 INotifyDataErrorInfo
.接下来,我添加了一个自定义 RowValidationErrorTemplate
As user mm8 pointed out, INotifyDataErrorInfo
is the approach to go. I removed the row validation rule and exposed a property named HasErros
in my view model that proxies the HasErrors
property of my model that in turn implements INotifyDataErrorInfo
. Next I added a custom 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
属性是我上面提到的代理属性.
Note the binding of Visibility
. The HasErrors
property is the proxy property I mentioned above.
最后,在 DataGrid
中使用该样式,如下所示
And finally, use that style in the DataGrid
as follows
<DataGrid RowHeaderStyle="{StaticResource MyDataGridRowHeaderStyle}"
...
在此处可以找到 BoolToVisibilityConverter
的实现.
推荐答案
不是向 DataGrid
的 RowValidationRules
属性添加 ValidationRule
您可以实现 INotifyDataErrorInfo 每当您要刷新行/项目的状态时,视图模型类中的a>接口,并引发其 ErrorChanged
事件.
Instead of adding a ValidationRule
to the RowValidationRules
property of the DataGrid
you could implement the INotifyDataErrorInfo interface in the view model class and raise its ErrorChanged
event whenever you want to refresh the status of a row/item.
这是实现数据验证的MVVM方法.不能使用 ValidationRule
.
This is the MVVM way of implementing data validation. Using a ValidationRule
is not.
WPF 4.5:使用INotifyDataErrorInfo界面验证数据: 查看全文