16

インターフェイスを使用して WPF アプリケーションに検証を実装しようとしていIDataErrorInfoますが、あまり望ましくない状況に遭遇しました。

コントロールが検証に失敗したときに使用されるこのテンプレートがあります

<ControlTemplate x:Key="errorTemplate">
    <DockPanel LastChildFill="true">
        <Border Background="Red" DockPanel.Dock="Right" Margin="5,0,0,0" Width="20" Height="20" CornerRadius="10"
                                    ToolTip="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
            <TextBlock Text="!" VerticalAlignment="Center" HorizontalAlignment="Center" FontWeight="Bold" Foreground="White" />
        </Border>
        <AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center" >
            <Border BorderBrush="red" BorderThickness="1" />
        </AdornedElementPlaceholder>
    </DockPanel>
</ControlTemplate>

コントロールの上にドッキング項目を表示するなど、検証に失敗したコントロールの上に何かを表示しようとするまでは、すべて問題ありません。

通常表示 コントロールの一部が非表示の場合の表示

これを回避し、エラー テンプレートをドック アイテムの下に表示するにはどうすればよいですか?

編集

TextBoxこれを修正するために でラップできることがわかりましたが、アプリケーションのすべてのコントロールAdornerDecoratorに対してこれを実行したくありません。または他の方法TextBoxで設定する方法はありますか?Style

編集2

おそらく、既定のTextBoxControlTemplate を変更して を含めることができAdornerDecoratorますが、WPF の既定のコントロール テンプレートを変更することにあまり熱心ではありません。他の提案は大歓迎です。

4

3 に答える 3

14

OK、コントロール テンプレートの変更を強制しない比較的単純な解決策を見つけました。

このようなものでそれぞれTextBoxを飾る代わりにAdornerDecorator

<StackPanel>
    <AdornerDecorator>
        <TextBox Text={Binding ...} />
    </AdornerDecorator>
    <AdornerDecorator>
        <TextBox Text={Binding ...} />
    </AdornerDecorator>
</StackPanel>

ビュー全体をAdornerDecoratorラップすると、同じ結果が得られます。

<AdornerDecorator>
    <StackPanel>
        <TextBox Text={Binding ...} />
        <TextBox Text={Binding ...} />
    </StackPanel>
</AdornerDecorator>

このようにして、ビューごとに最大 1 回定義できます。

于 2012-04-24T10:11:02.190 に答える
3

AdornerDecorator@AdiLester の優れた回答に基づいて、コントロールが基本クラスから派生していて、各コントロールの XAMLを入れたくない場合は、次のようにします。

public class MyBaseUserControl : UserControl
{
    public MyBaseUserControl()
    {

    }

    protected override void OnContentChanged(object oldContent, object newContent)
    {
        base.OnContentChanged(oldContent, newContent);

        if (!(newContent is AdornerDecorator))
        {
            this.RemoveLogicalChild(newContent);

            var decorator = new AdornerDecorator();
            decorator.Child = newContent as UIElement;

            this.Content = decorator;
        }
    }
}
于 2014-12-02T07:03:23.217 に答える
0

ここでは、簡単に適応できるスタイルの例を示します。

ErrorContent は、Errors[0] ではなく (Validation.Errors).CurrentItem.ErrorContent から取得されていることに注意してください。どちらも機能しますが、後者はここで概説されているように、飲み込まれた例外で出力ウィンドウを散らかします。

<Style x:Key="TextBoxStyle" TargetType="{x:Type TextBox}">
    <Setter Property="Margin" Value="0,0,16,0" />
    <Setter Property="VerticalAlignment" Value="Center" />
    <Setter Property="VerticalContentAlignment" Value="Center" />

    <!--
    Error handling
    -->
    <Setter Property="Validation.ErrorTemplate">
        <Setter.Value>
            <ControlTemplate>
                <DockPanel LastChildFill="True">
                    <TextBlock DockPanel.Dock="Right" Text=" *" 
                               Foreground="Red" FontWeight="Bold" FontSize="16" 
                               ToolTip="{Binding ElementName=placeholder, Path=AdornedElement.(Validation.Errors).CurrentItem.ErrorContent}"/>
                    <Border BorderBrush="Red"  BorderThickness="1">
                        <AdornedElementPlaceholder Name="placeholder"></AdornedElementPlaceholder>
                    </Border>
                </DockPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="True">
            <Setter Property="Background" Value="LightYellow"/>
        </Trigger>
    </Style.Triggers>
</Style>
于 2012-04-24T10:05:12.293 に答える