38

我有一个带有验证规则的 TextBox,它位于 TabControl 的选项卡上。当验证规则失败时,默认的 ErrorTemplate 正确显示(文本框周围的红色边框)。
但是,如果切换到另一个选项卡,然后返回到带有 TextBox 的选项卡,则 ErrorTemplate 突出显示消失了。如果 TextBox 发生更改,则仍会调用验证规则并返回 false,但仍不会显示错误突出显示。
只有当文本内容更改为有效然后再次变为无效时,highligh 才会恢复。
如果文本内容无效,我希望切换到另一个选项卡并返回会保留无效的突出显示。任何获得这种行为的想法都非常受欢迎。
xml:

<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 提示是在装饰层中绘制的。当您切换选项卡时,该图层将被丢弃。

于 2012-03-28T17:17:12.950 回答
14

只是针对特殊情况的补充:我遇到了类似的问题,现在我正在使用类似于 Dylan 代码的解决方案。

不同之处在于我的 TabItem 包含 GroupBox 并且 TextBox 在其中。在这种情况下,AdornerDecorator 必须在 GroupBox 本身中,而不是 TabItem 的直接后代。

所以这不起作用:

<TabItem>
    <AdornerDecorator>
        <Grid>
            <GroupBox>
                <Grid>
                    <TextBox>...<TextBox/>
                </Grid>
            </GroupBox>
        </Grid>
    </AdornerDecorator>
</TabItem>

但这确实:

<TabItem>
    <Grid>
        <GroupBox>
            <AdornerDecorator>
                <Grid>
                    <TextBox>...<TextBox/>
                </Grid>
            </AdornerDecorator>
        </GroupBox>
    </Grid>
</TabItem>

我之所以添加它,是因为我无法轻松找到解决方案,甚至文档AdornerLayer.GetAdornerLayer()(尽管不确定它是否适用于此处)指出This static method traverses up the visual tree starting at the specified Visual and returns the first adorner layer found.- 但也许它也会在某个时候停止,这在文档中尚不清楚。

于 2015-11-25T08:28:24.687 回答
7

正如 Dylan 所解释的,这是因为绘制验证错误的 Adorner 层在选项卡切换时被丢弃。所以你需要用AdornerDecorator.

我创建了一个将of自动包装在 an 中的行为,因此不必在所有 TabItems 上手动完成。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 回答