38

TabControl のタブにある検証規則を持つ TextBox があります。検証ルールが失敗した場合、デフォルトの ErrorTemplate が正しく表示されます (TextBox の周りの赤い境界線)。
ただし、別のタブに切り替えてから、TextBox のあるタブに戻ると、ErrorTemplate ハイライトが消えます。TextBox に変更がある場合、検証ルールは引き続き呼び出され、false を返しますが、エラーの強調表示は表示されません。
テキストの内容が有効に変更され、再び無効に変更された場合にのみ、ハイライトが復活します。
テキスト コンテンツが無効な場合、別のタブに切り替えて元に戻すと、無効なハイライトが保持されることを望みます。この動作を実現するためのアイデアは大歓迎です。
xaml:

<TextBox Height="35" >
  <TextBox.Text>
    <Binding Path="pan_id" UpdateSourceTrigger="PropertyChanged">
      <Binding.ValidationRules>
        <ps:PanIdValidation />
      </Binding.ValidationRules>
    </Binding>
  </TextBox.Text>
</TextBox>
4

3 に答える 3

68

TabItem は次のように定義する必要があります。

<TabItem Header="Foo">
    <Border>
        <AdornerDecorator>
            <Grid>
                <TextBox Height="35" >
                    <TextBox.Text>
                         <Binding Path="pan_id" UpdateSourceTrigger="PropertyChanged">
                             <Binding.ValidationRules>
                                 <ps:PanIdValidation />
                             </Binding.ValidationRules>
                          </Binding>
                      </TextBox.Text>
                  </TextBox>
              </Grid>
          </AdornerDecorator>
      </Border>
  </TabItem>

問題は、Validation.Error キューが Adorner レイヤーに描画されることです。タブを切り替えると、そのレイヤーは破棄されます。

于 2012-03-28T17:17:12.950 に答える
7

ディランが説明したように、これは検証エラーが描画される Adorner レイヤーがタブ スイッチで破棄されるためです。したがって、コンテンツを でラップする必要がありますAdornerDecorator

すべての TabItem で手動で行う必要がないように、を に自動的にラップする動作を作成しました。ContentTabItemAdornerDecorator

public static class AdornerBehavior
{
    public static bool GetWrapWithAdornerDecorator(TabItem tabItem)
    {
        return (bool)tabItem.GetValue(WrapWithAdornerDecoratorProperty);
    }
    public static void SetWrapWithAdornerDecorator(TabItem tabItem, bool value)
    {
        tabItem.SetValue(WrapWithAdornerDecoratorProperty, value);
    }

    // Using a DependencyProperty as the backing store for WrapWithAdornerDecorator.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty WrapWithAdornerDecoratorProperty =
        DependencyProperty.RegisterAttached("WrapWithAdornerDecorator", typeof(bool), typeof(AdornerBehavior), new UIPropertyMetadata(false, OnWrapWithAdornerDecoratorChanged));

    public static void OnWrapWithAdornerDecoratorChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
    {
        var tabItem = o as TabItem;
        if (tabItem == null) return;

        if(e.NewValue as bool? == true)
        {
            if (tabItem.Content is AdornerDecorator) return;
            var content = tabItem.Content as UIElement;
            tabItem.Content = null;
            tabItem.Content = new AdornerDecorator { Child = content };
        }
        if(e.NewValue as bool? == false)
        {
            if (tabItem.Content is AdornerDecorator)
            {
                var decorator= tabItem.Content as AdornerDecorator;
                var content = decorator.Child;
                decorator.Child = null;
                tabItem.Content = content;
            }
        }
    }
}

TabItemsデフォルトのスタイルを介して、すべてにこの動作を設定できます。

<Style TargetType="TabItem">
    <Setter Property="b:AdornerBehavior.WrapWithAdornerDecorator" Value="True"></Setter>
</Style>

b動作が配置されている名前空間で、次のようになります (プロジェクトごとに異なります)。

xmlns:b="clr-namespace:Styling.Behaviors;assembly=Styling"
于 2016-01-24T18:00:45.097 に答える