在基础数据更改时验证行 [英] Validate row when underlying data changes

查看:17
本文介绍了在基础数据更改时验证行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

想象一个 DataGrid,它的 ItemsSource 设置为一个 ObservableCollection.该集合为 DataGrid 中的每一行提供了一个视图模型.视图模型反过来提供显示在一行中的数据和可能更改此数据的命令.此外,我向 DataGridRowValidationRules 属性添加了一条规则.如果我输入了无效数据,此验证规则可以正常工作.

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的实现.

推荐答案

而不是将 ValidationRule 添加到 DataGridRowValidationRules 属性你可以实现 INotifyDataErrorInfo 视图模型类中的接口,并在您想要刷新行/项目的状态时引发其 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 接口验证数据: https://social.technet.microsoft.com/wiki/contents/articles/19490.wpf-4-5-validating-data-in-using-the-inotifydataerrorinfo-interface.aspx

这篇关于在基础数据更改时验证行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆