WPF:在DataGridComboxColumn中显示验证工具提示

WPF:在DataGridComboxColumn中显示验证工具提示,wpf,Wpf,我有一个DataGrid,其中有几个组合框列。使用ViewModel中的IDataErrorInfo界面验证这些值。当鼠标悬停在适当的单元格上时,工具提示应显示验证错误 实现此行为的正常方法是使用ElementStyle,如下所示: <DataGridComboBoxColumn ...> <DataGridComboBoxColumn.ElementStyle> <Style TargetType="ComboBox"> ...

我有一个DataGrid,其中有几个组合框列。使用ViewModel中的IDataErrorInfo界面验证这些值。当鼠标悬停在适当的单元格上时,工具提示应显示验证错误

实现此行为的正常方法是使用ElementStyle,如下所示:

<DataGridComboBoxColumn ...>
  <DataGridComboBoxColumn.ElementStyle>
    <Style TargetType="ComboBox">
      ...
      <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="true">
          <Setter Property="ToolTip"
                  Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
        </Trigger>
      </Style.Triggers>
    </Style>
  </DataGridComboBoxColumn.ElementStyle>
</DataGridComboBoxColumn>

...
这适用于DataGridTextColumns,但不适用于DataGridComboxColumns(不显示工具提示)。如果相同的代码用于编辑元素样式,则一切正常。但仅当单元格处于编辑模式时(如预期,因为EditingElementStyle仅在编辑模式下使用)

在WWW中找到的解决此问题的方法建议使用如下手机样式:

<DataGridComboBoxColumn ...>
  <DataGridComboBoxColumn.CellStyle>
    <Style TargetType="DataGridCell">
      <Style.Triggers>
        <DataTrigger Binding="{Binding Path=(Validation.HasError), RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridRow}}}" 
                     Value="True">
          <Setter Property="ToolTip"
                            Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridRow}}, Path=(Validation.Errors)[0].ErrorContent}" />
        </DataTrigger>
      </Style.Triggers>
    </Style>
  </DataGridComboBoxColumn.CellStyle>
</DataGridComboBoxColumn>

这种方法使用DataGrid行和硬编码索引来获取错误。我觉得这很容易出错。无论如何,只要行中只有一个验证错误,它就应该工作。但是,一旦同一行中有两个或多个验证错误,它就不再工作了。每个工具提示都显示第一个验证错误(由于硬编码索引):

因此,我似乎很自然地使用DataGridCell而不是DataGridRow来获取错误(请参见下面绑定中的RelativeSource):


但使用此样式时,不会显示工具提示。输出窗口中没有错误或警告。将PresentationOnTraceSources.TraceLevel=High添加到触发器绑定会显示HasError属性返回false

删除工具提示绑定周围的触发器时,Validation.Errors似乎不包含任何值:

System.Windows.Data Warning: 56 : Created BindingExpression (hash=13069983) for Binding (hash=50848483)
System.Windows.Data Warning: 58 :   Path: '(0)[0].ErrorContent'
System.Windows.Data Warning: 60 : BindingExpression (hash=13069983): Default mode resolved to OneWay
System.Windows.Data Warning: 61 : BindingExpression (hash=13069983): Default update trigger resolved to PropertyChanged
System.Windows.Data Warning: 62 : BindingExpression (hash=13069983): Attach to System.Windows.Controls.DataGridCell.ToolTip (hash=21168757)
System.Windows.Data Warning: 67 : BindingExpression (hash=13069983): Resolving source 
System.Windows.Data Warning: 70 : BindingExpression (hash=13069983): Found data context element: <null> (OK)
System.Windows.Data Warning: 72 :   RelativeSource.Self found DataGridCell (hash=21168757)
System.Windows.Data Warning: 78 : BindingExpression (hash=13069983): Activate with root item DataGridCell (hash=21168757)
System.Windows.Data Warning: 108 : BindingExpression (hash=13069983):   At level 0 - for DataGridCell.(Validation.Errors) found accessor DependencyProperty(Errors)
System.Windows.Data Warning: 104 : BindingExpression (hash=13069983): Replace item at level 0 with DataGridCell (hash=21168757), using accessor DependencyProperty(Errors)
System.Windows.Data Warning: 101 : BindingExpression (hash=13069983): GetValue at level 0 from DataGridCell (hash=21168757) using DependencyProperty(Errors): ReadOnlyObservableCollection`1 (hash=51278326 Count=0)
System.Windows.Data Warning: 109 : BindingExpression (hash=13069983):   At level 1 - for ReadOnlyObservableCollection`1[] found accessor RuntimePropertyInfo(Item)
System.Windows.Data Warning: 104 : BindingExpression (hash=13069983): Replace item at level 1 with ReadOnlyObservableCollection`1 (hash=51278326 Count=0), using accessor RuntimePropertyInfo(Item)
System.Windows.Data Warning: 101 : BindingExpression (hash=13069983): GetValue at level 1 from ReadOnlyObservableCollection`1 (hash=51278326 Count=0) using RuntimePropertyInfo(Item): {IListIndexOutOfRange}
System.Windows.Data Error: 17 : Cannot get 'Item[]' value (type 'ValidationError') from '(Validation.Errors)' (type 'ReadOnlyObservableCollection`1'). BindingExpression:Path=(0)[0].ErrorContent; DataItem='DataGridCell' (Name=''); target element is 'DataGridCell' (Name=''); target property is 'ToolTip' (type 'Object') ArgumentOutOfRangeException:'System.ArgumentOutOfRangeException: Das angegebene Argument liegt außerhalb des gültigen Wertebereichs.
Parametername: index'
System.Windows.Data Warning: 103 : BindingExpression (hash=13069983): Replace item at level 2 with {NullDataItem}
System.Windows.Data Warning: 80 : BindingExpression (hash=13069983): TransferValue - got raw value {DependencyProperty.UnsetValue}
System.Windows.Data Warning: 88 : BindingExpression (hash=13069983): TransferValue - using fallback/default value <null>
System.Windows.Data Warning: 89 : BindingExpression (hash=13069983): TransferValue - using final value <null>
System.Windows.Data警告:56:为绑定(哈希=50848483)创建了BindingExpression(哈希=13069983)
System.Windows.Data警告:58:路径:'(0)[0]。ErrorContent'
System.Windows.Data警告:60:BindingExpression(哈希=13069983):默认模式解析为单向
System.Windows.Data警告:61:BindingExpression(哈希=13069983):默认更新触发器已解析为PropertyChanged
System.Windows.Data警告:62:BindingExpression(哈希值=13069983):附加到System.Windows.Controls.DataGridCell.ToolTip(哈希值=21168757)
System.Windows.Data警告:67:BindingExpression(哈希=13069983):正在解析源
System.Windows.Data警告:70:BindingExpression(哈希=13069983):找到数据上下文元素:(确定)
System.Windows.Data警告:72:RelativeSource.Self-found DataGridCell(哈希=21168757)
System.Windows.Data警告:78:BindingExpression(哈希值=13069983):使用根项DataGridCell(哈希值=21168757)激活
System.Windows.Data警告:108:BindingExpression(哈希=13069983):级别0-对于DataGridCell.(Validation.Errors)找到了访问器依赖属性(Errors)
System.Windows.Data警告:104:BindingExpression(哈希=13069983):使用访问器依赖属性(错误)将级别0处的项替换为DataGridCell(哈希=21168757)
System.Windows.Data警告:101:BindingExpression(哈希值=13069983):使用DependencyProperty从DataGridCell(哈希值=21168757)获取级别0处的值(错误):ReadOnlyObservableCollection`1(哈希值=51278326计数=0)
System.Windows.Data警告:109:BindingExpression(hash=13069983):位于级别1-对于ReadOnlyObservableCollection`1[]已找到访问者RuntimePropertyInfo(项)
System.Windows.Data警告:104:BindingExpression(哈希值=13069983):使用访问器RuntimePropertyInfo(项)将级别1上的项替换为ReadOnlyObservableCollection`1(哈希值=51278326计数=0)
System.Windows.Data警告:101:BindingExpression(hash=13069983):使用RuntimePropertyInfo(项):{IListIndexOutOfRange}从ReadOnlyObservableCollection`1(hash=51278326 Count=0)获取级别1的值
System.Windows.Data错误:17:无法从(Validation.Errors)(类型“ReadOnlyObservableCollection”“1”)获取“项[]”值(类型“ValidationError”)。BindingExpression:Path=(0)[0]。ErrorContent;DataItem='DataGridCell'(名称='';目标元素是“DataGridCell”(名称=“”);目标属性为“ToolTip”(类型为“Object”)ArgumentOutOfRangeException:“System.ArgumentOutOfRangeException:Das angegebene Argument liegt außerhalb des gültigen Wertebereichs。
参数名称:索引'
System.Windows.Data警告:103:BindingExpression(哈希=13069983):将级别2的项替换为{NullDataItem}
System.Windows.Data警告:80:BindingExpression(hash=13069983):TransferValue-获取原始值{DependencyProperty.UnsetValue}
System.Windows.Data警告:88:BindingExpression(哈希=13069983):TransferValue-使用回退/默认值
System.Windows.Data警告:89:BindingExpression(哈希=13069983):TransferValue-使用最终值
有人能解决这个问题吗

有人能解决这个问题吗

为什么不简单地用
DataGridTemplateColumn
替换
datagridcomboxcolumn
,并在CellTemplate中使用文本块和CellEditingTemplate中使用组合框呢

更加灵活,结果完全相同。除此之外,它实际上解决了您的问题:

<DataGridTemplateColumn Header="...">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name, ValidatesOnDataErrors=True}">
                <TextBlock.Style>
                    <Style TargetType="TextBlock">
                        <Style.Triggers>
                            <Trigger Property="Validation.HasError" Value="true">
                                <Setter Property="ToolTip" Value="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={RelativeSource Self}}"/>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </TextBlock.Style>
            </TextBlock>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <ComboBox ItemsSource="{Binding SomeItems, RelativeSource={RelativeSource AncestorType=Window}}"
                                      SelectedItem="{Binding Name, ValidatesOnDataErrors=True}">
                <ComboBox.Style>
                    <Style TargetType="ComboBox">
                        <Style.Triggers>
                            <Trigger Property="Validation.HasError" Value="true">
                                <Setter Property="ToolTip" Value="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={RelativeSource Self}}"/>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </ComboBox.Style>
            </ComboBox>
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

当DataGridComboBoxColumn处于只读模式时,不会显示“真实”组合框<
<DataGridTemplateColumn Header="...">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name, ValidatesOnDataErrors=True}">
                <TextBlock.Style>
                    <Style TargetType="TextBlock">
                        <Style.Triggers>
                            <Trigger Property="Validation.HasError" Value="true">
                                <Setter Property="ToolTip" Value="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={RelativeSource Self}}"/>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </TextBlock.Style>
            </TextBlock>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <ComboBox ItemsSource="{Binding SomeItems, RelativeSource={RelativeSource AncestorType=Window}}"
                                      SelectedItem="{Binding Name, ValidatesOnDataErrors=True}">
                <ComboBox.Style>
                    <Style TargetType="ComboBox">
                        <Style.Triggers>
                            <Trigger Property="Validation.HasError" Value="true">
                                <Setter Property="ToolTip" Value="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={RelativeSource Self}}"/>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </ComboBox.Style>
            </ComboBox>
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>