想象一下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
的实现。
答案 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