如何在不覆盖现有样式的情况下向 WPF 自定义控件添加触发器?

Posted

技术标签:

【中文标题】如何在不覆盖现有样式的情况下向 WPF 自定义控件添加触发器?【英文标题】:How to add a trigger to a WPF custom control without overriding the existing style? 【发布时间】:2010-12-02 11:47:08 【问题描述】:

我正在创建一个从切换按钮扩展的简单自定义控件,它允许用户直接在 XAML 中指定选中和未选中的内容。它运作良好,但它基于触发器,我不知道如何定义触发器,除非在样式中。如果我定义了样式,那么我会丢失自定义控件之外的任何设置。

我想做的只是将此触发器附加到控件其他位置的任何现有样式集。

这是样式/触发器的 XAML。

<ToggleButton.Style>
    <Style TargetType="x:Type ToggleButton" BasedOn="StaticResource x:Type ToggleButton">
        <Setter Property="Content" Value="Binding RelativeSource=RelativeSource Self, Path=UncheckedContent" />
        <Style.Triggers>
            <Trigger Property="IsChecked" Value="True">
                <Setter Property="Content"
                        Value="Binding RelativeSource=RelativeSource Self, Path=CheckedContent" />
            </Trigger>
        </Style.Triggers>
    </Style>
</ToggleButton.Style>

我尝试使用默认类型通过 BasedOn 继承样式,但如果自定义控件具有由其父项设置的显式样式,它将不起作用。我也考虑过 EventTriggers 但我不相信会有初始化控件的事件。

感谢任何人提供的任何帮助。 :)

【问题讨论】:

【参考方案1】:

只是为了澄清这里的术语:用户控件是派生自 UserControl 类的控件。如果我理解正确,您从 ToggleButton 派生以添加 UncheckedContent 和 CheckedContent 属性。在这种情况下,您创建了一个自定义控件。如果我们就通用术语达成一致,总是更容易理解:)

据我所知,您不能在 XAML 中进行这样的通用样式继承。您始终必须明确指定另一种样式所基于的样式。您的样式可以基于 ToggleButton 的默认样式或特定的其他样式。如果您无法构建尊重这一点的样式继承链,那么这种方法将行不通。

但是既然你有一个自定义控件,你不能为它写一个默认样式,它基于这样的默认切换按钮样式吗?

<Style TargetType="x:Type CustomToggleButton" 
       BasedOn="StaticResource x:Type ToggleButton">

然后,每当您将显式样式应用于切换按钮时,您都会指定它基于默认的切换按钮样式。

您还可以在 Themes\Generic.xaml 中为包含上述触发器的新切换按钮编写(默认)控件模板。在混合中,您可以获得切换按钮的默认模板的副本(“编辑模板”->“编辑副本”),因此您可以确保您的切换按钮看起来与普通切换按钮完全相同。然后将上面的触发器合并到该模板中。

顺便说一句:您不必为了添加新属性而创建新控件。您可以使用attached properties 向现有控件添加新属性。它们可以像普通属性一样从 XAML 中使用。

【讨论】:

感谢您的意见,非常有帮助。我走了一条不同的路线,并在后面的代码中扩展了现有样式以添加我的触发器,而不会破坏现有的触发器。您提出的 BasedOn 建议我已经尝试过了,如果设置了明确的样式,它就不起作用。不过,我是从您的想法中得出的,所以我将其标记为答案。附加属性的想法非常好,我也进行了更改,谢谢。 :) 你介意发布一些你所做的细节吗?我也想做同样的事情。

以上是关于如何在不覆盖现有样式的情况下向 WPF 自定义控件添加触发器?的主要内容,如果未能解决你的问题,请参考以下文章

Jackson:如何在不修改 POJO 的情况下向 JSON 添加自定义属性

如何在不覆盖的情况下向 Firebase Firestore 添加值?

在不破坏现有基类的情况下向具有许多派生类的抽象基类添加新方法

如果样式已经设置,如何覆盖 WPF 子控件样式?

如何在不干扰本机控件的情况下向我的 HTML5 视频添加点击播放?

自定义 WPF 控件的好处