WPF控件模板:如何为TemplateBinding提供默认值?

36

我正在编写一个WPF控件,它是Button的子类。然后我在Themes\generic.xaml中提供了一个默认样式,它看起来像这样(简化):

<Style TargetType="{x:Type WPFControls:MyButton}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type WPFControls:MyButton}">
                <Button 
                    x:Name="PART_Button"
                    Background="{TemplateBinding Background}"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

我希望用户有机会更改控件的背景,但如果用户没有提供值,我希望提供默认值。我该怎么做?

当我像发布的代码那样做时,除非用户明确指定它们(这实际上迫使用户始终提供某些值),否则Background和BorderBrush都为null(不存在),但是标准的Windows控件(如Button)提供了默认外观,仍然可以由用户自定义。如何在我的控件中实现这一点?

谢谢!

Michael Morton 的解决方案:

您可以在样式中提供默认值作为setter:

<Style TargetType="{x:Type TestTemplate:MyButton}">
    <Setter Property="Background" Value="Red" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TestTemplate:MyButton}">
                <Button 
                    x:Name="PART_Button"
                    IsEnabled="{TemplateBinding IsEnabled}"
                    Content="{TemplateBinding Content}"
                    Background="{TemplateBinding Background}"
                    />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

使用方法:

<StackPanel>
    <TestTemplate:MyButton Background="Blue">Explicitly blue</TestTemplate:MyButton>
    <TestTemplate:MyButton>Naturally red</TestTemplate:MyButton>
</StackPanel>
4个回答

22
你可以在样式表中定义这两个属性的setter方法。
例如,一些通用的定义:
<LinearGradientBrush x:Key="ButtonNormalBackground" EndPoint="0,1" StartPoint="0,0">
    <GradientStop Color="#F3F3F3" Offset="0"/>
    <GradientStop Color="#EBEBEB" Offset="0.5"/>
    <GradientStop Color="#DDDDDD" Offset="0.5"/>
    <GradientStop Color="#CDCDCD" Offset="1"/>
</LinearGradientBrush>

<SolidColorBrush x:Key="ButtonNormalBorder" Color="#FF707070"/>

然后,在你的样式定义中:

<Setter Property="Background" Value="{StaticResource ButtonNormalBackground}" />
<Setter Property="BorderBrush" Value="{StaticResource ButtonNormalBorder}" />

1
很好,这就是我想知道的。我把你的解决方案添加到了问题中。谢谢! - Tomáš Kafka

6
<Style TargetType="{x:Type WPFControls:MyButton}">
    <Setter Property="Background" Value="Black">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type WPFControls:MyButton}">
                <Button 
                    x:Name="PART_Button"
                    Background="{TemplateBinding Background}"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

请注意第二个字符串,我将黑色设置为背景的默认值。


太棒了!现在我可以在特定的控件上指定自定义背景... - Gauss

3

当您为控件声明依赖属性时,还需将默认属性声明为UIPropertyMetadata。

此属性的默认值为Brushes.Red,正如最后一行所示。

  public Brush MyBrush {
     get { return (Brush)GetValue(MyBrushProperty); }
     set { SetValue(MyBrushProperty, value); }
  }

  public static readonly DependencyProperty MyBrushProperty =
      DependencyProperty.Register("MyBrush", typeof(Brush), typeof(MyQsFeature), new UIPropertyMetadata(Brushes.Red));

另一种方法是在自定义控件的构造函数中设置默认颜色,因为构造函数总是在用户设置任何属性之前调用,如果用户未设置它们,则它们将默认为您的设置。实际上,它们总是由您设置,然后任何用户设置都会覆盖您的设置。如果您想设置诸如“背景”之类的属性,而不是实际创建它们,那么这种方法非常有效,这些属性来自于您继承的基类。


1
谢谢,但我正在使用来自祖先的附加属性,因此默认值的技巧不可行。至于在构造函数中设置它 - 那就是在代码中编写xaml(这不应该是必要的),并且它不能由模板更改,因此我认为这不是Microsoft控件的实现方式。 - Tomáš Kafka

2

您可以通过创建示例实例并引用其属性来“继承”Button元素的默认样式:

<Button x:Key="DefaultButton"/>

<Style TargetType="{x:Type TestTemplate:MyButton}">
        <Setter Property="Background"
                Value="{Binding Path=Background, Source={StaticResource DefaultButton}}" />
</Style>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接