【问题标题】:WPF CustomControl overwriteable default styleWPF CustomControl 可覆盖的默认样式
【发布时间】:2021-08-06 08:40:01
【问题描述】:

我有一个问题,关于在 wpf 的自定义控件中实现默认样式。 我已经编写了自己的 IconButton 控件,该控件将两个可自定义的 TextBlocks 放入一个按钮控件中,这主要是有效的。这个样子是这样的:

<Style TargetType="{x:Type MyButton}" BasedOn="{StaticResource {x:Type Button}}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type MyButton}">
                    <Button>
                        <Button.Content>
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition />
                                    <ColumnDefinition />
                                </Grid.ColumnDefinitions>
                                <TextBlock
                                    Grid.Column="0"
                                    [...]>
                                </TextBlock>

                                <TextBlock
                                    Grid.Column="1"
                                    VerticalAlignment="Center"
                                    Text="{TemplateBinding Text}"
                                    [...]>
                                </TextBlock>
                            </Grid>
                        </Button.Content>
                    </Button>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

在相应的 MyButton.cs 中,我定义了两个 TextBlock 中引用的所有 DependencyProperties,如下所示:

public static readonly DependencyProperty TextProperty = DependencyProperty.Register(nameof(Text), typeof(string), typeof(IconButton), new FrameworkPropertyMetadata(string.Empty));

所有这些都有效。我知道我可以在 DepedencyProperty(此处为 string.Empty)中有一个默认值,如果我这样做,则可以通过在使用“MyButton”时定义一个新值来完全覆盖它。 但是显然,按钮也有常规样式,例如宽度和高度,由于某种原因,当我以我定义的样式定义它们时,我无法覆盖这些样式。除此之外,我还计划以默认样式为我的新依赖属性定义默认值(只是为了方便),但它似乎也不起作用。

我尝试过的两件事: (1) 使用按钮样式(显然只适用于按钮的 DepdendencyProperties 不适用于我的新按钮)

<Button.Style>
   <Style TargetType="{x:Type Button}">
      <Setter Property="MinWidth" Value="300"/>
      <Setter Property="MinHeight" Value="24"/>
      <Setter Property="FontSize" Value="12"/>
   </Style>
</Button.Style>

或 (2) 在 TopLevel 上定义默认样式,即就像我用于模板的另一个常规设置器(也适用于我的新 DependencyProperties):

<Style TargetType="{x:Type MyButton}" BasedOn="{StaticResource {x:Type Button}}">
   <Setter Property="Template">...</Setter>
   <Setter Property="MinWidth">100</Setter>
</Style>

(2) 似乎是更好的解决方案,因为我认为它应该做我想做的一切,但它根本不起作用。我的样式更改均未应用。 (1) 正在工作,但显然仅适用于按钮样式。但是,也无法覆盖这些值,即当我使用时:

 <local:MyButton [...] MinWidth="100"/>

它不会覆盖我所期望的样式!

请记住,我是初学者,这是我在 WPF 中的第一个自定义控件!谢谢大家的建议。

【问题讨论】:

  • 如果要创建自定义控件,则需要设置默认模板键。在 WPF 中习惯上这个键是元素类型。您是否安装了此密钥?您是否创建了具有默认样式的主题?
  • 嘿,设置默认模板密钥并安装该密钥是什么意思?这不是这条线的作用:

标签: wpf wpf-controls


【解决方案1】:

一个可行的解决方案是已经指出的方法,它在创建 DependencyProperty 时设置默认值。 对于已继承的其他 DependencyProperties,可以在静态构造函数中覆盖它们,如下所示:

static MyButton()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(MyButton), new FrameworkPropertyMetadata(typeof(MyButton)));
            Button.FontSizeProperty.OverrideMetadata(typeof(MyButton), new FrameworkPropertyMetadata(12D, FrameworkPropertyMetadataOptions.Inherits));
            Button.MinWidthProperty.OverrideMetadata(typeof(MyButton), new FrameworkPropertyMetadata(120d, FrameworkPropertyMetadataOptions.AffectsMeasure));
            Button.MinHeightProperty.OverrideMetadata(typeof(MyButton), new FrameworkPropertyMetadata(24d, FrameworkPropertyMetadataOptions.AffectsMeasure));
        }

即您可以轻松访问其他 DependencyProperties 并覆盖其默认值。 “模板”属性中应用的样式似乎是硬编码的,我找不到更改它们的方法,而这是我更愿意做的。

任何方式:这是在 C# 代码中与在 XAML 中的对比,但它确实可以工作并完成所需的一切。

【讨论】:

  • 为什么是DefaultStyleKeyPropertyButton.FontSizeProperty?在派生的 Button 类中,FontSizeProperty.OverrideMetadata(...) 就足够了。
【解决方案2】:

嘿,设置默认模板密钥并安装该密钥是什么意思?

当您使用 Studio“项目”->“添加新项...”->“自定义控件 (WPF)”创建自定义控件时,会在项目中插入一个类模板。
在这个模板中,Stuia 总是插入一个静态构造函数来定义你的类的默认键:

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

此外,“主题”文件夹将添加到项目中,其中将存储“Generic.xaml”文件。
这是一个资源字典文件,它为项目中创建的所有自定义控件定义了默认模板。

【讨论】:

  • 啊,是的,我已经完全按照您所指出的那样做了。这对于制作自定义控件来说是非常基本的,否则您将无法将自己的 DependencyProperties 添加到 CustomControl。
  • DependecyProperty 与它无关。我们需要一个字符串来指定元素类型的默认键:DefaultStyleKeyProperty.OverrideMetadata(...)。如果没有这一行,您的元素将默认为基本类型模板。在您的情况下,这可能是一个按钮。要获得更详细的答案,请显示包含静态构造函数的元素代码部分和“Generic.xaml”文件的内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多