2017-02-01 44 views
3

私はDataGridに複数のComboBox列があるとします。値は、ViewModelのIDataErrorInfoインターフェイスを使用して検証されます。適切なセルにカーソルを移動すると、ツールチップに検証エラーが表示されます。WPF:検証ツールチップをDataGridComboBoxColumnに表示

この動作を達成するための通常のアプローチは、次のような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のために動作しますがDataGridComboBoxColumnsためない(何のツールチップが表示されません)。同じコードをに編集する場合は、 ElementStyleを編集するだけで問題ありません。しかし、セルが編集モードにある場合のみ(EditingElementStyleは編集モードでのみ使用されるため) WWWで見つかったこの問題の

ソリューションは、このようCellStyleを使用することが推奨されています

<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 とエラーを取得するには、ハードコーディングされたインデックスを使用しています。これは私にとって非常に誤りのようです。とにかく、行内に唯一の検証エラーが存在する限り、動作するはずです。しかし、同じ行に2つ以上の検証エラーが発生するとすぐに、それはもはや機能しません。すべてのツールチップは、(理由は、ハードコードされたインデックスの)最初の検証エラーを示しています。私はエラーを取得する代わりにDataGridRowのDataGridCellを使用するため

Tooltips

だから、(下のバインディングでRelativeSourceを参照してください自然に思えます):

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

ただし、このスタイルを使用すると、ツールチップは表示されません。出力ウィンドウにエラーや警告はありません。 PresentationTraceSources.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> 

は、誰かがこの問題の解決策を持っていますか?

答えて

1

誰かがこの問題の解決策を持っていますか?

なぜあなたは単にDataGridTemplateColumnDataGridComboBoxColumnを交換し、CellTemplate内のTextBlockと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は読み取り専用モードである、表示さない「本当の」コンボボックスはありません。

+0

私は現在TextBlockComboBoxをTextBlockに置き換えるためにDataGridComboBoxColum.GenerateElement()をオーバーライドしようとしています。これは基本的にあなたと同じアプローチです。 SelectedValuePathとDisplayMemberPathで作業しているので、あまり簡単ではありません。 – fss

+0

カスタムクラスを作成し、ComboBoxをTextBlockに置き換えるためにGenerateElement()メソッドをオーバーライドしようとしているのはなぜですか?これは意味をなさない。私の答えで示唆したようにDataGridTemplateColumnを使用してください。 – mm8

+0

多くのカスタマイズを含む従来のコード;-) – fss

関連する問題