【问题标题】:Template Binding with Attached Properties带有附加属性的模板绑定
【发布时间】:2012-03-03 04:49:28
【问题描述】:

我的按钮有一个标准样式,但我希望样式的某些部分是可配置的。例如为按钮触发 MouseOver 时出现边框,我希望边框颜色可配置。

在这篇文章之后:http://www.thomaslevesque.com/2011/10/01/wpf-creating-parameterized-styles-with-attached-properties/ 我想我可以使用附加属性和 TemplateBinding 来实现这一点。

我创建了以下附加属性:

public static class ThemeProperties
{
    public static Brush GetButtonBorderColour(DependencyObject obj)
    {
        return (Brush)obj.GetValue(ButtonBorderColourProperty);
    }

    public static void SetButtonBorderColour(DependencyObject obj, Brush value)
    {
        obj.SetValue(ButtonBorderColourProperty, value);
    }

    public static readonly DependencyProperty ButtonBorderColourProperty =
        DependencyProperty.RegisterAttached(
            "ButtonBorderColour",
            typeof(Brush),
            typeof(ThemeProperties),
            new FrameworkPropertyMetadata(Brushes.Black, FrameworkPropertyMetadataOptions.Inherits));
}

我这样设置属性:

<Button Style="{StaticResource RedButton}" local:ThemeProperties.ButtonBorderColour="#B20000"/>

而我的风格是这样的:

<Window.Resources>
    <Style x:Key="RedButton" TargetType="Button">
        <Setter Property="OverridesDefaultStyle" Value="True"/>
        <Setter Property="Margin" Value="2"/>
        <Setter Property="FontFamily" Value="Tahoma"/>
        <Setter Property="FontSize" Value="11px"/>
        <Setter Property="FontWeight" Value="Bold"/>
        <Setter Property="Foreground" Value="White"/>
        <Setter Property="MinHeight" Value="25" />

        <Setter Property="FocusVisualStyle" Value="{StaticResource MyFocusVisual}" />
        <Setter Property="Background" >
            <Setter.Value>
                <LinearGradientBrush StartPoint="0,0" EndPoint="0,1" >
                    <GradientStop Color="#FECCBF" Offset="0.2"/>
                    <GradientStop Color="Red" Offset="0.85"/>
                    <GradientStop Color="#FECCBF" Offset="1"/>
                </LinearGradientBrush>
            </Setter.Value>
        </Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Border Name="border" BorderThickness="1" Padding="4,2" BorderBrush="Transparent" CornerRadius="3" Background="{TemplateBinding Background}">
                        <Grid >
                            <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Name="content"/>
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="border" Property="BorderBrush" Value="{TemplateBinding local:ThemeProperties.ButtonBorderColour}" />
                            <Setter Property="Foreground" Value="#B20000" />
                        </Trigger>
                        <Trigger Property="IsPressed" Value="True">
                            <Setter Property="Background" >
                                <Setter.Value>
                                    <LinearGradientBrush StartPoint="0,0" EndPoint="0,1" >
                                        <GradientStop Color="#FECCBF" Offset="0.35"/>
                                        <GradientStop Color="Red" Offset="0.95"/>
                                        <GradientStop Color="#FECCBF" Offset="1"/>
                                    </LinearGradientBrush>
                                </Setter.Value>
                            </Setter>
                            <Setter TargetName="content" Property="RenderTransform" >
                                <Setter.Value>
                                    <TranslateTransform Y="1.0" />
                                </Setter.Value>
                            </Setter>
                        </Trigger>
                        <Trigger Property="IsDefaulted" Value="True">
                            <Setter TargetName="border" Property="BorderBrush" Value="#B20000" />
                        </Trigger>
                        <Trigger Property="IsFocused" Value="True">
                            <Setter TargetName="border" Property="BorderBrush" Value="#B20000" />
                        </Trigger>
                        <Trigger Property="IsEnabled" Value="False">
                            <Setter TargetName="border" Property="Opacity" Value="0.7" />
                            <Setter Property="Foreground" Value="Gray" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

关键线在哪里

<Trigger Property="IsMouseOver" Value="True">
    <Setter TargetName="border" Property="BorderBrush" Value="{TemplateBinding local:ThemeProperties.ButtonBorderColour}" />
    <Setter Property="Foreground" Value="#B20000" />
</Trigger>

据我所知,这应该可以,但是在运行时在上面的行中出现以下错误:

无法将属性“Value”中的值转换为“”类型的对象。 标记文件中的对象“System.Windows.Setter”出错

我在这里做错了吗?我是 WPF 的新手,不知道出了什么问题,因为附加属性的类型是 Brush,这是我希望 BorderBrush 属性想要的。

【问题讨论】:

    标签: wpf attached-properties templatebinding


    【解决方案1】:

    我认为 TemplateBinding 是在编译时评估的,因此您无法在 Setter 中动态设置 TemplateBinding,请尝试改用 Binding(见下文)。

    <Setter TargetName="border" Property="BorderBrush" 
            Value="{Binding Path=(local:ThemeProperties.ButtonBorderColour),
                            RelativeSource={RelativeSource TemplatedParent}}"/>
    

    希望这会有所帮助。

    【讨论】:

    • 嘿,我编辑了我的答案,它现在应该可以工作了。这是一个语法错误,对此感到抱歉。
    • 感谢小川,效果很好。我还可以看到我的代码与链接网页上的示例之间的区别,因为该示例未在我之前不欣赏的 setter 中使用 TemplateBinding。再次感谢!
    • 我不明白为什么我的相同案例在设计时不起作用(但在运行时起作用)-stackoverflow.com/questions/41614676/…
    【解决方案2】:

    试试这个:

    <Setter TargetName="border" Property="BorderBrush" Value="{TemplateBinding Path=(local:ThemeProperties.ButtonBorderColour)}" />
    

    不同之处在于属性周围的括号表示它是附加属性。

    【讨论】:

    • 不幸的是,这似乎没有被识别为有效的语法,它只是返回类型错误(找不到本地:ThemeProperties。
    • 对不起,前面需要Path=。这是 XAML 解析器中的一个怪癖。我会更新我的答案。
    • 仍然不高兴,仍然标记为无效语法,并出现错误“在类型 'TemplateBindingExtension' 中找不到属性 'Path'”。
    • 按照小川的建议将TemplateBinding改为Binding。
    • 这个答案无效,它仍然建议TemplateBinding。我建议更新它。
    猜你喜欢
    • 2022-01-07
    • 2011-09-17
    • 2012-09-24
    • 2017-07-02
    • 2011-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多