WPF 错误样式仅在选项卡控件的可见选项卡上正确呈现

WPF Error Styles only being rendered properly on visible tab of a tab control(WPF 错误样式仅在选项卡控件的可见选项卡上正确呈现)
本文介绍了WPF 错误样式仅在选项卡控件的可见选项卡上正确呈现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

我有一个数据对象用于包含支持 INotifyPropertyChangedIDataErrorInfo 的 UI 数据.最初,我将所有 UI 控件显示在一个大型 WPF 应用程序中,并且很高兴看到通过这种自定义样式标记的错误:

I have a data object used to contain my UI data that supports INotifyPropertyChanged and IDataErrorInfo. Originally I had all of the UI controls displaying in one big WPF application and was happily seeing errors flagged via this custom style:

    <!-- Set error style for textboxes -->
    <Style x:Key="txtBoxErrStyle" TargetType="{x:Type TextBox}">
        <Style.Triggers>
            <Trigger Property="Validation.HasError" Value="True">
                <Setter Property="ToolTip" 
                            Value="{Binding RelativeSource={x:Static RelativeSource.Self}, 
                            Path=(Validation.Errors)[0].ErrorContent}" />
            </Trigger>
        </Style.Triggers>

        <Setter Property="Validation.ErrorTemplate">
            <Setter.Value>
                <ControlTemplate>
                    <DockPanel DockPanel.Dock="Right">
                        <AdornedElementPlaceholder />
                        <Image Source="Error.png"
                                   Height="16"
                                   Width="16"
                                   ToolTip="{Binding Path=AdornedElement.ToolTip, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Adorner}}}" />
                    </DockPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

我今天正在重新组织程序,并决定将各种 UI 控件分布在 TabControl 的几页上.我为此使用的结构布局是:

I was reorganizing the program today and decided to distribute the various UI controls over several pages of a TabControl. The structure layout I am using for this is:

<tabcontrol>
    <tabitem>
        <AdornerDecorator>
           [.. various Stack Panels, Groups and UI controls moved from original layout ..]
        </AdornerDecorator>
    </tabItem>
    <tabitem>
        <AdornerDecorator>
           [.. various Stack Panels, Groups and UI controls moved from original layout ..]
        </AdornerDecorator>
    </tabItem>

    ...
 </tabcontrol>

(我正在使用 AdornerDecorator,正如我在之前的程序中所经历的那样,交换标签页时错误样式没有被重新呈现.我不记得我在哪里看到的,但它确实有帮助我出去.)

(I am using the AdornerDecorator as I had experienced in a previous program the error style not being re-rendered when swapping tab pages. I can't remember where I saw this but it did help me out.)

现在当我启动我的程序时,错误样式正确呈现在程序启动时打开的 TabItem 上,但没有正确呈现在另一个(隐藏的)TabItems.当我选择(并显示)其中一个 TabItem 时,会设置错误样式的工具提示,但不会显示错误图标图像.

Now when I start my program the error style correctly renders on the TabItem that is open when the program starts, but does not correctly render on the other (hidden) TabItems. When I select (and reveal) one of those TabItems the tool-tip of the error style is set, but the error icon image is not displayed.

我还测试了删除自定义样式并恢复为文本框的默认 WPF 错误样式,我仍然得到类似的行为,即隐藏的 TabItem 上的控件周围没有红色框当程序打开时.

I also tested removing the custom style and revert back to the default WPF error style for textboxes and I still get a similar behaviour, i.e. no red box around the control on the TabItems that are hidden when the program opens.

所以我似乎完全错过了阻止错误样式正确呈现的东西,而不是打开的选项卡项.有什么想法吗?

So it seems that I am totally missing something that is stopping the error styles from correctly rendering on other than the open tab Item. Any ideas?

编辑 9 月 3 日 更改了描述以支持更好地理解我所看到的内容

Edit Sep 3 Changed description to support a better understanding of what I have seen

谈 2014 年的似曾相识

现在是 2014 年 11 月,今天我遇到了这个愚蠢的 WPF 问题,错误模板未显示在选项卡控制器中显示的项目上.我脑海中的某件事表明我以前见过这个问题.于是我用谷歌搜索,首先弹出的是我自己 2009 年的问题!

It's November 2014 and today I had this stupid WPF problem with error templates not showing up on items presented in a tab controller. Something in the back of my mind suggests that I have seen this problem before. So I google, and the first thing that pops up is my own question from 2009!

这次我看到了我上次解决问题后添加的来自 dkl 的评论.所以我尝试了他的方式并使用了这个解决方案(效果很好,我不需要在我的选项卡控件上撒上 Adorner 控件):

This time I see the comment from dkl which was added after I solved things the last time around. So I tried it his way and used this solution (which worked well and I didn't need to sprinkle an Adorner control over my tab controls):

<Style x:Key="TextBoxErrorStyle" TargetType="TextBox">
    <Style.Triggers>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition Property="Validation.HasError" Value="True" />
                <Condition Property="IsVisible" Value="True" />
            </MultiTrigger.Conditions>
            <Setter Property="Validation.ErrorTemplate">
                <Setter.Value>
                    <ControlTemplate>
                        <DockPanel LastChildFill="True">
                            <TextBlock  DockPanel.Dock="Right" 
                                Foreground="Red"
                                FontSize="14pt" 
                                 Margin="-15,0,0,0" FontWeight="Bold">*
                            </TextBlock>
                            <Border BorderBrush="Red" BorderThickness="2">
                                <AdornedElementPlaceholder Name="controlWithError"/>
                            </Border>
                        </DockPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="ToolTip" 
                    Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors).CurrentItem.ErrorContent}" />
        </MultiTrigger>
    </Style.Triggers>
</Style>

推荐答案

(我正在使用 AdornerDecorator在以前的计划中经历过错误样式没有被重新渲染交换标签页时.我不能记得我在哪里看到的,但确实如此帮帮我)

(I am using the AdornerDecorator as I had experienced in a previous program the error style not being re-rendered when swapping tab pages. I can't remember where I saw this but it did help me out)

大概这个非常重要的提示来自 Karl Shifflets 博客,至少他在讨论同一个主题:WPF 验证错误消失切换 TabItems 时 TabControl 内部.

Presumably this indeed important tip originates from Karl Shifflets blog, at least he's addressing the same topic: WPF Validation Errors Disappear Inside TabControl When Switching TabItems.

鉴于此,您的问题可能只是相关的,即上面的提示/代码确保有一个专用的 AdornerLayer 现在用于每个选项卡项,因为切换选项卡时父元素的装饰层会被丢弃.这个专用的装饰层似乎仍然需要一些特殊处理,例如问题 WPF ErrorTemplate visible什么时候不专注?这基本上是在处理你的问题.因此,我建议您将后者的概述解决方案与您的风格相结合并扩展,并尝试以下方法(尽管目前尚未测试代码):

Given this your issue might just be related, i.e. the tip/code above ensures there is a dedicated AdornerLayer for every tab item now, as the adorner layer of the parent element is discarded when you switch tabs. This dedicated adorner layer appears to still require some special treatment though, see for example question WPF ErrorTemplate visible when not focused? which is basically dealing with your issue upside down. Consequently I'd suggest you combine and expand the outlined solution for the latter with your style and try the following (untested code as of now though):

<Style x:Key="ErrorTemplate" TargetType="{x:Type TextBox}">
    <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="True">...</Trigger>
        <Trigger Property="IsVisible" Value="false">
            <Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>
        </Trigger>
        <Trigger Property="IsVisible" Value="true">
            <Setter Property="Validation.ErrorTemplate">
                <Setter.Value>...</Setter.Value>
            </Setter>
        </Trigger>
    </Style.Triggers>
</Style>

请参阅我关于您更新 单选按钮错误样式 的评论,它也尝试类似解决您可能的相关问题;你真的在那里尝试过我的建议吗?

See my comment regarding your update of Radio Button Error Style too, which tries to similarly address your likely related question; have you actually tried my suggestion there?

有关装饰器架构的更多详细信息,请参阅装饰器概述.

See Adorners Overview for more details on the adorner architecture.

这篇关于WPF 错误样式仅在选项卡控件的可见选项卡上正确呈现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

相关文档推荐

Custom Error Queue Name when using EasyNetQ for RabbitMQ?(使用 EasyNetQ for RabbitMQ 时自定义错误队列名称?)
How to generate password_hash for RabbitMQ Management HTTP API(如何为 RabbitMQ 管理 HTTP API 生成密码哈希)
Rabbitmq Ack or Nack, leaving messages on the queue(Rabbitmq Ack 或 Nack,将消息留在队列中)
Setup RabbitMQ consumer in ASP.NET Core application(在 ASP.NET Core 应用程序中设置 RabbitMQ 消费者)
Specify Publish timeouts in mass transit(指定公共交通中的发布超时)
RabbitMQ asynchronous support(RabbitMQ 异步支持)