【问题标题】:Use a dependency property to set a value in ControlTemplate trigger使用依赖属性在 ControlTemplate 触发器中设置值
【发布时间】:2019-12-21 22:57:55
【问题描述】:

创建一个使用图像作为背景的按钮,当按下按钮时,使用不同的图像作为背景。继承自button,增加了两个ImageBrush类型的依赖属性,一个是PressedBackground。后面会有一个枚举类型属性,用来选择在‘PressedImage’和‘NormalImage’中加载哪组图片资源。

在 controltemplate 中,使用“IsPressed”的数据触发器,将背景属性设置为“PressedBackground”中的图像画笔。 但是当运行时,在我们没有背景的情况下,调试跟踪说“无法使用绑定检索值并且不存在有效的后备值。

问题是在 onpressed 数据触发器中将图像画笔从依赖属性加载到背景属性中。我已经尝试了各种方法来获取背景属性的值,但没有成功

自定义类 sn-p

public class QuantaImageButton : Button
{

    static QuantaImageButton()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(QuantaImageButton),
    new FrameworkPropertyMetadata(typeof(QuantaImageButton)));

    }


    public static readonly DependencyProperty PressedBackgroundProperty = DependencyProperty.Register(
        "PressedBackground", typeof(ImageBrush), typeof(QuantaImageButton), new PropertyMetadata(default(ImageBrush)));

    public ImageBrush PressedBackground
    {
        get { return (ImageBrush) GetValue(PressedBackgroundProperty); }
        set { SetValue(PressedBackgroundProperty, value); }
    }

    // other dependency properties
}

风格是:

<Style x:Key="BtnQuanta" TargetType="controls:QuantaImageButton">
    <Setter Property="PressedBackground" Value="{StaticResource BtnMenuMediumDownImage}"/>
    <Setter Property="Background" Value="{StaticResource BtnMenuMediumUpImage}"/>
    <Setter Property= "Width" Value="500" />
    <Setter Property="Height" Value="470"/>
    <Setter Property="FontFamily" Value="Arial"/>
    <Setter Property="FontSize" Value="52"/>
    <Setter Property="Foreground" Value="White"/>
    <Setter Property="BorderThickness" Value="0"/>
    <Setter Property="Template" Value="{StaticResource QuantaBtnControlTemplate}"/>
</Style>


<ControlTemplate x:Key="QuantaBtnControlTemplate" TargetType="{x:Type    controls:QuantaImageButton}">
    <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
        <ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
    </Border>
    <ControlTemplate.Triggers>
        <Trigger Property="IsPressed" Value="True">
            <Setter Property="Background" Value="{Binding PressedBackground, RelativeSource={RelativeSource TemplatedParent} }"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

【问题讨论】:

  • 为什么不改用StaticResource?在您的样式中使用对静态资源的引用并动态更改它。另请查看Output 窗口,它会为您提供有关它实际在哪里寻找您指向的资源的信息。
  • 我们有大约 40 种不同的按钮样式,所以这将涉及 40 种不同的样式,我们想要一种样式和一个模板,并且我们使用枚举的依赖属性来设置“按钮样式”,代码如下在两个 imagebrush 属性中设置正确的资源图像之后 - 我需要知道如何在控件模板中访问依赖属性值 - 正确
  • 在这种情况下,您可以使用BasedOn,让所有样式都意识到这一点。不知道您为什么坚持为它已经拥有的按钮创建功能。我想我在这里错过了更大的画面,但如果你想想你在用这个按钮做什么,那就是什么都不存在了。
  • 资源是图像刷类型,如果样式设置了背景属性就可以工作-所以我知道资源没问题。
  • VS 调试在按下按钮时显示此内容

标签: wpf properties triggers controltemplate


【解决方案1】:

如果您添加TargetName="border" 以将背景应用于模板内的边框,则{RelativeSource TemplatedParent} 有效:

<ControlTemplate.Triggers>
    <Trigger Property="IsPressed" Value="True">
        <Setter TargetName="border" Property="Background" 
                Value="{Binding Path=PressedBackground, RelativeSource={RelativeSource TemplatedParent} }"/>
    </Trigger>
</ControlTemplate.Triggers>

添加 TargetName 会改变绑定的目标,显然它会影响 RelativeSource 的解析。但是我无法在文档中的任何地方指出这种细微的差异

【讨论】:

    【解决方案2】:

    我找到了答案——正如调试文本所暗示的——它找不到该属性。绑定不正确 - 我已将其更改为:

     <ControlTemplate.Triggers>
            <Trigger Property="IsPressed" Value="True">
                <Setter Property="Background" Value="{Binding PressedBackground, RelativeSource={RelativeSource Self} }"/>
            </Trigger>
        </ControlTemplate.Triggers>
    

    对于没有新属性的本地对象,RelativeSource 必须是 {RelativeSource Self},而不是 TemplateParent。

    作为一个“老”的 Winforms 人,转而使用 WPF - 如果有人能提供有关这种绑定以及如何使用它的更多解释的链接,那将是一个很大的帮助。

    【讨论】:

    • 这对我有帮助。出于某种原因,在 ControlTemplate 本身中您需要使用 TemplatedParent,但在 ControlTemplate.Triggers 部分中您需要使用 Self。非常混乱。
    猜你喜欢
    • 2016-04-04
    • 2011-08-04
    • 1970-01-01
    • 2019-06-27
    • 2021-11-08
    • 2011-02-13
    • 2010-12-17
    • 2014-08-14
    • 1970-01-01
    相关资源
    最近更新 更多