none
Validation.Errorsの値が取得できない RRS feed

  • 質問

  • 初めての投稿です。
    データの入力用にContentControlから派生し、「表題を持つ」「コンテンツの検証エラーを表示する」という機能を持った簡単なカスタムコントロールを作ろうとしています。
    簡単なデータを用いて実際にコンテンツの検証エラーを認識してエラーアイコンを表示する所まではうまく動作するのですが、肝心のToolTipに検証エラーのメッセージの内容が反映されません。
    以下、必要最小限に絞ったカスタムコントロールです。

        public class TestContent : ContentControl
    
        {
    
            static TestContent()
    
            {
    
                DefaultStyleKeyProperty.OverrideMetadata(typeof(TestContent), new FrameworkPropertyMetadata(typeof(TestContent)));
    
            }
    
        }
    
    
    
    

        <Style TargetType="{x:Type local:TestContent}">
    
            <Setter Property="Validation.ValidationAdornerSiteFor" Value="{Binding Content, RelativeSource={RelativeSource Self}}" />
    
            <Setter Property="Validation.ErrorTemplate">
    
                <Setter.Value>
    
                    <ControlTemplate>
    
                        <AdornedElementPlaceholder />
    
                    </ControlTemplate>
    
                </Setter.Value>
    
            </Setter>
    
            <Setter Property="Template">
    
                <Setter.Value>
    
                    <ControlTemplate TargetType="{x:Type local:TestContent}">
    
                        <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="True">
    
                            <DockPanel>
    
                                <Border DockPanel.Dock="Left" Width="140">
    
                                    <DockPanel>
    
                                        <Border x:Name="icon"
    
                                                DockPanel.Dock="Right" Width="12" Height="12" Margin="1,0" VerticalAlignment="Center"
    
                                                Background="Violet" BorderBrush="DarkRed" BorderThickness="0.5" CornerRadius="2" Visibility="Hidden">
    
                                            <TextBlock Foreground="White" FontSize="10" FontWeight="Bold" VerticalAlignment="Center" HorizontalAlignment="Center" Text="!" />
    
                                        </Border>
    
                                        <ContentControl Content="Example" FontSize="10.5" VerticalAlignment="Center" />
    
                                    </DockPanel>
    
                                </Border>
    
                                <ContentPresenter Content="{TemplateBinding Content}" />
    
                            </DockPanel>
    
                        </Border>
    
                        <ControlTemplate.Triggers>
    
                            <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.ValidationAdornerSiteFor).(Validation.HasError)}" Value="True">
    
                                <Setter TargetName="icon" Property="Visibility" Value="Visible" />
    
                                <Setter TargetName="icon" Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.ValidationAdornerSiteFor).(Validation.Errors)[0].ErrorContent}" />
    
                            </DataTrigger>
    
                        </ControlTemplate.Triggers>
    
                    </ControlTemplate>
    
                </Setter.Value>
    
            </Setter>
    
        </Style>
    
    
    
    

    このカスタムコントロールをウィンドウに配置し、以下のようにしてテストしています。
            private string _Test;
    
            public string Test
    
            {
    
                get { return _Test; }
    
                set
    
                {
    
                    if (_Test != value)
    
                    {
    
                        _Test = value;
    
                        if (_Test == "111") { throw new ApplicationException("テストエラー!!!"); }
    
                    }
    
                }
    
            }
    
            <TextBox DockPanel.Dock="Top"  Text="{Binding ElementName=_mainWindow, Path=Test, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}">
    
                <TextBox.Style>
    
                    <Style TargetType="TextBox">
    
                        <Style.Triggers>
    
                            <Trigger Property="Validation.HasError" Value="True">
    
                                <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
    
                            </Trigger>
    
                        </Style.Triggers>
    
                    </Style>
    
                </TextBox.Style>
    
            </TextBox>
    
            <app:TestContent DockPanel.Dock="Top" x:Name="_TestHeader">
    
                <TextBox Name="_TestTextBox" Text="{Binding ElementName=_mainWindow, Path=Test, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}" />
    
            </app:TestContent>
    
    
    上の TextBox は値をセットした際に発生した例外をキャッチし、ToolTipでエラーが正しく表示されています。
    が、カスタムコントロールの方はエラーを認識していてもToolTipがうまく表示されません。
    カスタムコントロールの方のToolTipにBindingではなく適当な即値("error!!"など)を指定した場合は表示されますので、おそらくBindingの指定がおかしいのだとは思うのですが……いろいろ試してうまく行きませんでした。

    よければご教授お願いします。
    2010年1月22日 9:45

回答

  • < Setter TargetName = " icon " Property = " ToolTip " Value = " {Binding RelativeSource={RelativeSource Self}, Path=(Validation.ValidationAdornerSiteFor).(Validation.Errors)[0].ErrorContent} " />
    カスタムコントロール用 Template の Triggers 内の Setter ですが、この Setter.Value で使用しているバインディングに問題があります。
    この Setter は TargetName が icon になっているので、icon に対して働きます。当然、RelatveSource.Self は icon を指すことになるのです。TestContent.Content の ValidationAdornerSiteFor は TestContent 自身に設定してあり icon ではないので Validation.GetValidationAdornerSiteFor(icon) は null になります。
    Template 内のバインディングでテンプレート親のコントロール(つまりこの場合は TestContent ですね)をバインディングソースに指定するには、RelativeSource={RelatveSource TemplatedParent} などを使います。
    • 回答としてマーク K.Ktouth 2010年1月23日 8:46
    2010年1月22日 12:57

すべての返信

  • < Setter TargetName = " icon " Property = " ToolTip " Value = " {Binding RelativeSource={RelativeSource Self}, Path=(Validation.ValidationAdornerSiteFor).(Validation.Errors)[0].ErrorContent} " />
    カスタムコントロール用 Template の Triggers 内の Setter ですが、この Setter.Value で使用しているバインディングに問題があります。
    この Setter は TargetName が icon になっているので、icon に対して働きます。当然、RelatveSource.Self は icon を指すことになるのです。TestContent.Content の ValidationAdornerSiteFor は TestContent 自身に設定してあり icon ではないので Validation.GetValidationAdornerSiteFor(icon) は null になります。
    Template 内のバインディングでテンプレート親のコントロール(つまりこの場合は TestContent ですね)をバインディングソースに指定するには、RelativeSource={RelatveSource TemplatedParent} などを使います。
    • 回答としてマーク K.Ktouth 2010年1月23日 8:46
    2010年1月22日 12:57
  • 早速試してみたところ、まさしくその通りでした。ありがとうございます。
    こんな単純なミスだったとは思いもしませんでした……もっとマニュアルを精査しないと。
    2010年1月23日 8:48