検証をトリガーするために INotifyDataErrorInfo を使用しています。
Validation.ErrorTemplate からコントロールを取得できません。その高さを装飾された要素の下マージンに追加して、装飾された要素の下にエラーが表示され、下のコントロールが下に移動するようにするには、スタックパネルの実際の高さが必要です。
コンバーター内でビジュアル ツリーを使用しようとしましたが、何も起こりません。また、XAML を使用してみましたが、まだ何もありません。
<converters:ErrorsToMarginMultiConverter x:Key="ErrorsToMarginMultiConverter"/>
<Style TargetType="{x:Type Control}" x:Key="ValidationStyle">
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="Height" Value="25"/>
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<StackPanel>
<!--The Original Control-->
<AdornedElementPlaceholder x:Name="OriginalControl"/>
<!--The Errors List-->
<ItemsControl ItemsSource="{Binding}" x:Name="ErrorItemsControl">
<ItemsControl.ItemTemplate>
<DataTemplate>
<BulletDecorator Width="{Binding ElementName=OriginalControl, Path=ActualWidth, UpdateSourceTrigger=PropertyChanged}">
<BulletDecorator.Bullet>
<Ellipse Fill="Red" Width="5" Height="5"/>
</BulletDecorator.Bullet>
<TextBlock Text="{Binding ErrorContent, StringFormat=' {0}'}" Foreground="Red" TextWrapping="Wrap"/>
</BulletDecorator>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="BorderThickness" Value="2" />
<Setter Property="BorderBrush" Value="DarkRed" />
<Setter Property="Margin">
<Setter.Value>
<MultiBinding Converter="{StaticResource ErrorsToMarginMultiConverter}" UpdateSourceTrigger="PropertyChanged">
<Binding Path="(Validation.Errors)" RelativeSource="{RelativeSource Self}"/>
<Binding RelativeSource="{RelativeSource Self}"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
検証エラー テンプレート内のコントロールを何らかの形でコンバーターへのパラメーターとして取得するか、実際の高さを抽出するためにコンバーター内のコードでそれらを取得することを期待しています。
このテンプレートでデフォルトで何が起こっているかを次に示します。これ が期待される結果です
検証エラーが発生したときに期待される結果を得るために、元のコントロール (TextBox) に下マージンとして追加するために、そのスタックパネルの高さを取得したいと考えています。 ツリー ビュー コンバーターのコード サンプル
編集:私は部分的な解決策を見つけることができました、
public object Convert(object[] value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null)
{
var adornedElement = value[1] as Control;
var adornerLayer = System.Windows.Documents.AdornerLayer.GetAdornerLayer(adornedElement);
var templatedAdorner = adornerLayer.GetAdorners(adornedElement);
var margin = adornedElement.Margin;
margin.Bottom = 20;
if (templatedAdorner != null && templatedAdorner.Length > 0)
margin.Bottom = templatedAdorner[0].ActualHeight;
return margin;
}
return value;
}
問題は、このコンバーターが 2 回トリガーされることです。1 回目は以前の検証エラーをクリアするとき、2 回目はエラーを追加するときです。初めて templatedAdorner を見つけて読み取るのは、実際の高さです。しかし、2 回目は adorner レイヤーが見つかったが、templatedAdorned が存在しない場合 (null)。私のビジュアルツリーでは、それらを見ることができます。また、ビューには正しく表示されますが、検証エラーの数も正しくありません。
トリガーは ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName)); です。INotifyDataErrorInfo から。