WPF DataGrid Validation.HasError 始终为 false (MVVM)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17951045/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 09:19:10  来源:igfitidea点击:

WPF DataGrid Validation.HasError is always false (MVVM)

wpfvalidationxamldatagridmvvm-light

提问by M C

I have some trouble getting the Information if there are ValidationErrors inside the Datagrid / the DataGridCells.

如果 Datagrid/DataGridCells 中存在 ValidationErrors,我在获取信息时会遇到一些麻烦。

What I'm trying to do is to Disable a Button via Commands(CanExecute) basedOn the presence or absence of Validation Errors. Therefore I bind the the DataGrid's Validation.HasError to the CommandParameter on the Button.

我想要做的是根据验证错误的存在或不存在通过命令(CanExecute)禁用按钮。因此,我将 DataGrid 的 Validation.HasError 绑定到按钮上的 CommandParameter。

The Validation is implemented with IDataErrorInfoin the ViewModeland works just fine. Any DataGridCell containing a wrong value gets a red Border and a Tooltip describing the Error.

验证是在ViewModel 中使用IDataErrorInfo实现的,并且工作得很好。任何包含错误值的 DataGridCell 都会获得一个红色边框和一个描述错误的工具提示。

What I just cant get to work is Binding that Button's CommandParameterto Validation.HasError on the DataGrid. If i debug this issue, Validation.HasError is always false. Why? And how can i fix it?

我无法开始工作的是将该按钮的CommandParameter绑定到 DataGrid 上的 Validation.HasError。如果我调试这个问题,Validation.HasError 总是假的。为什么?我该如何解决?

I tried virtually every "solution" I found here and elsewhere on the net. Nothing worked so far.

我几乎尝试了在这里和网上其他地方找到的所有“解决方案”。到目前为止没有任何效果。

My DataGrid XAML:

我的 DataGrid XAML:

<DataGrid x:Uid="DataGrid_1"
          Name="SomeDataGrid"
          Grid.Column="0"
          Grid.Row="1"
          Grid.RowSpan="2"
          ItemsSource="{Binding SomeItems}"
          SelectedItem="{Binding SomeSelectedItem, Mode=TwoWay}"
          CanUserSortColumns="False"
          CanUserAddRows="False"
          CanUserDeleteRows="False"
          IsReadOnly="False"
          IsSynchronizedWithCurrentItem="True"
          IsTabStop="True"
          IsTextSearchEnabled="True"
          >
    <DataGrid.Resources>
        <SolidColorBrush x:Uid="SolidColorBrush_1"
                         x:Key="{x:Static SystemColors.ControlBrushKey}"
                         Color="{x:Static SystemColors.HighlightColor}" />
    </DataGrid.Resources>
    <DataGrid.Columns>
        <DataGridTemplateColumn x:Uid="Comlumn1"
                                x:Name="Comlumn1"
                                Header="SomeHeader"
                                Width="auto">
            <DataGridTemplateColumn.CellEditingTemplate>
                <DataTemplate x:Uid="DataTemplate_1">
                    <ComboBox x:Uid="ComboBox_7"
                              ItemsSource="{Binding DataContext.Attributes,Source={StaticResource ProxyElement}}"
                              SelectedItem="{Binding Attribute, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"
                              DisplayMemberPath="DESCRIPTION"
                              IsEditable="False"
                              IsTextSearchEnabled="False"
                              Margin="0"
                              Padding="0" />
                </DataTemplate>
            </DataGridTemplateColumn.CellEditingTemplate>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate x:Uid="DataTemplate_2">
                    <TextBlock x:Uid="TextBlock_15"
                               Text="{Binding Attribute, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"
                               ToolTip="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={x:Static RelativeSource.Self}}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>

        <DataGridTextColumn x:Uid="DataGridTextColumn_2"
                            Header="Value"
                            Width="auto"
                            Binding="{Binding VALUE, ValidatesOnDataErrors=True}">
            <DataGridTextColumn.ElementStyle>
                <Style x:Uid="Style_4"
                       TargetType="{x:Type TextBlock}">
                    <Setter x:Uid="Setter_4"
                            Property="DataGridCell.ToolTip"
                            Value="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={x:Static RelativeSource.Self}}" />
                </Style>
            </DataGridTextColumn.ElementStyle>
        </DataGridTextColumn>
        <DataGridTextColumn x:Uid="DataGridTextColumn_3"
                            Header="Unit"
                            Width="auto"
                            Binding="{Binding UNIT, Mode=OneWay, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}"
                            IsReadOnly="True" />
        <DataGridTextColumn x:Uid="DataGridTextColumn_4"
                            Header="Remark"
                            Width="auto"
                            Binding="{Binding REMARK}" />
    </DataGrid.Columns>
</DataGrid>

The Button I want to Bind to the DataGrid Validation.Errors:

我想绑定到 DataGrid Validation.Errors 的按钮:

    <Button x:Uid="Button_1"
            Content=" + "
            Command="{Binding AddItemCommand}"
            CommandParameter="{Binding (Validation.HasError), ElementName=SomeDataGrid}" />

回答by M C

Ok i finally worked it out! The following Method from heredoes indeed work, but only afterthe Window containing my Datagrid is fully loaded(eg. in the Window / Usercontrol Loaded EventHandler):

好吧,我终于解决了!从下面的方法在这里确实工作,但只有包含我的Datagrid中窗口被完全加载(例如,在窗口/用户控件加载事件处理程序。):

public bool IsValid(DependencyObject parent)
{
    if (Validation.GetHasError(parent))
        return false;

    // Validate all the bindings on the children
    for (int i = 0; i != VisualTreeHelper.GetChildrenCount(parent); ++i)
    {
        DependencyObject child = VisualTreeHelper.GetChild(parent, i);
        if (!IsValid(child)) { return false; }
    }

    return true;
}