WPF DataGrid の 列に [StringLength(10)]public ReactiveProperty<string> Name { get; } とかをバインドして、 Name.SetValidateAttribute(() => Name); とかすると自動で列検証とかができてエラー表示のために RowHeader に "!" が表示されてエラーセルには赤枠が表示されるはずなのだけど、セルの幅が入力文字列よりも小さい場合に以下のようになる。
見た通り、赤い書くが Name 列の対象セルからはみ出している。
Validation.ErrorTemplate を頑張って書いてみたりいろいろやったけども、どうやっても回避できない。
Google Gemini によると
WPFの設計: Adorner は、装飾対象のコントロールの境界をわずかに超えて描画することで、エラーや装飾をより目立たせるように意図されています。また、Adorner は通常のレイアウトとは独立したレイヤー(AdornerLayer)に描画されるため、コントロールのClipToBounds(領域内でのクリッピング)を無視して描画されます。
結果: DataGrid のようなセルベースのコントロールに適用されると、この「境界をわずかに超える」動作が、隣接するセルとの重なり(侵食)として現れます。
らしいけども Adorner がちゃんとクライアント領域を計算してないっぽく見える。
結局どうするかというと、対象の DataGridCell のスタイルか CellStyleなどで以下のようにする
<Setter Property="Validation.ErrorTemplate" Value="{x:Null}" />
つまり ErrorTemplateの使用をやめる。
具体的にDataGridTextColumnなどではこうなる
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors).CurrentItem.ErrorContent}" />
</Trigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.CellStyle>
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="Validation.ErrorTemplate" Value="{x:Null}" />
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
ToolTip ではエラーの存在に気付きにくいこと、赤文字だと場合によってはエラーがあるとは認識できない場合があることについては注意が必要。
ちなみに以下は効果がない
<DataGridTextColumn Binding="{Binding Name.Value,UpdateSourceTrigger=PropertyChanged}" Header="Name" Width="144">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="BorderBrush" Value="Blue" />
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors).CurrentItem.ErrorContent}" />
<Setter Property="BorderBrush" Value="Red" />
<Setter Property="BorderThickness" Value="10" />
</Trigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.CellStyle>
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="Validation.ErrorTemplate" Value="{x:Null}" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
DataGridCell に Validation.HasError は伝播しない。
