关于wpf:具有附加属性的模板绑定

Template Binding with Attached Properties

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

紧随本文之后:http://www.thomaslevesque.com/2011/10/01/wpf-creating-parameterized-styles-with-attached-properties/我认为我可以使用附加属性和TemplateBinding来实现此目的。

我创建了以下附加属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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));
}

我将属性设置如下:

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

我的风格如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<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>

关键线在哪里

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

据我所知,这应该起作用,但是在运行过程中,在上面的行中出现以下错误:

Cannot convert the value in attribute 'Value' to object of type ''.
Error at object 'System.Windows.Setter' in markup file

我在这里做错了什么吗? 我是WPF的新手,无法弄清楚出了什么问题,因为附加属性的Type是Brush,这是我期望Border的BorderBrush属性所需要的。


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

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

希望这可以帮助。


试试这个:

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

区别在于,属性的括号表示该属性是附加属性。