在基础数据更改时验证行

时间:2017-02-27 01:01:25

标签: wpf wpfdatagrid

想象一下DataGrid,其ItemsSource设置为ObservableCollection。此集合为DataGrid中的每一行提供了一个视图模型。视图模型依次提供显示在一行中的数据和可能更改此数据的命令。另外,我在RowValidationRules的{​​{1}}属性中添加了一条规则。如果我输入无效数据,此验证规则可以正常工作。

但是,如果我通过视图模型提供的命令将无效数据更改为有效数据,则只有DataGrid中的当前行失去焦点时才会再次触发行验证规则。因此,显示的数据实际上可能有效,但DataGrid仍显示红色感叹号,表明它具有无效数据。在当前行失去焦点或我再次输入有效数据之前,情况仍然如此。

如何强制对当前行进行第二次验证?我已设置DataGrid,但这并没有解决问题。我也实现了INotifyPropertyChanged接口,但这也没有解决问题。

解决方案

正如用户mm8指出的那样,ValidatesOnTargetUpdated="True"是最佳选择。我删除了行验证规则,并在我的视图模型中公开了一个名为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的实现。

2 个答案:

答案 0 :(得分:2)

您可以在视图模型类中实现INotifyDataErrorInfo接口,并提升其ValidationRule,而不是将RowValidationRules添加到DataGrid的{​​{1}}属性中。每当您想要刷新行/项的状态时都会发生事件。

这是实现数据验证的MVVM方式。使用ErrorChanged不是。

WPF 4.5:使用INotifyDataErrorInfo接口验证数据: https://social.technet.microsoft.com/wiki/contents/articles/19490.wpf-4-5-validating-data-in-using-the-inotifydataerrorinfo-interface.aspx

答案 1 :(得分:1)

您可以处理CellEditEnding,找到行并致电UpdateSources的{​​{1}}:

BindingGroup

另外,请注意为绑定设置 private void dataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e) { DataGrid dg = sender as DataGrid; foreach (var r in dg.Items) { DataGridRow row = dg.ItemContainerGenerator.ContainerFromItem(r) as DataGridRow; if (row != null) row.BindingGroup.UpdateSources(); } }

修改

请注意,您还可以使用UpdateSourceTrigger=PropertyChanged

EventTrigger

其中 <DataGrid x:Name="dataGrid1" ItemsSource="{Binding Models}" DataContext="{Binding}"> <i:Interaction.Triggers> <i:EventTrigger EventName="CellEditEnding" > <i:InvokeCommandAction Command="{Binding PCommand}" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=DataGrid, Mode=FindAncestor}}"> </i:InvokeCommandAction> </i:EventTrigger> </i:Interaction.Triggers> </DataGrid> 位于ViewModel中并且:

PCommand