如何访问由 "coder" 设置的属性,例如 xaml 字典中的覆盖(命名)按钮模板

How to access Properties set by "coder" inside say an overriding (named) Button Template in a xaml Dictionary

我正在努力为我正在开发的应用程序中的“按钮栏”按钮创建样式,但我希望开发人员能够通过以下方式指定按钮渐变填充等中使用的颜色在 Button 声明中添加 xaml BackGround、Foreground 和 BorderBrush 颜色代码。

我已经使用了完全未定义的“复制模板”技巧来获取控件的完整默认模板的副本,但我对所有重要颜色在样式内部进行硬编码的方式感到完全困惑,被重命名为诸如“Button.Static.Background”之类的名称,这些名称都使用附加到它们的硬编码颜色,例如:

<SolidColorBrush x:Key="Button.Pressed.Border" Color="#FF2C628B"/>
<SolidColorBrush x:Key="Button.Disabled.Background" Color="#FFF4F4F4"/>''

然后稍后在模板中通过这些名称引用它们。我真正希望能够做的是在模板中引用这些项目的用户定义属性,而不是硬编码值,但我似乎找不到这样做的方法。

例如,这是我正在尝试的方法,但它不起作用,尽管我没有收到任何此类错误。第一行是标准声明,接下来的两行是我想让用户在使用此样式以匹配他们喜欢的 background/foreground 配色方案时覆盖的内容。

<SolidColorBrush x:Key="Button.Static.Border" Color="Black"/>
<SolidColorBrush x:Key="Button.MouseOver.Background" Color="{DynamicResource Background}"/>
<SolidColorBrush x:Key="Button.MouseOver.Border" Color="{DynamicResource Border}"/>

稍后在模板中我们会看到:-

    <Trigger Property="IsMouseOver" Value="true">
   <Setter Property="Background" 
                        TargetName="border" 
                        Value="{StaticResource Button.MouseOver.Background}"/>
                            <Setter Property="BorderBrush" 
                        TargetName="border" 
                        Value="{StaticResource Button.MouseOver.Border}"/>
                        </Trigger>

''' 这就是我希望在发生鼠标悬停时使用用户定义的颜色(如果提供)而不是任何硬编码值的地方? . 我是不是太聪明了,还是有什么明智的方法可以做到这一点?

您可以基于几乎任何控件(本例为按钮)制作模板化控件,并扩展该控件。您可以添加属性以允许用户在使用 XAML 中的控件时指定颜色。当然,您必须设置默认颜色 - 可能是您在问题中使用的颜色。

这是我前几天写的关于如何创建可绑定控件的回答:

  • 答案中的重要部分是依赖属性和控件 Style 中的 Template 属性。您不需要创建新控件来使用TemplateBinding

您可以在那里使用相同的方法并实际添加任何您想要的 属性。前景、MouseOverForeground、MouseOverBackground 等

另一种方法是创建一个全局主题。您的所有控件都应使用此主题(您可能必须为每个控件创建自定义样式才能使用该主题)。

  • 您可以像在问题中所做的那样在资源字典中声明默认主题颜色。
  • 主题的好处是最终用户可以在 运行 时自定义主题,例如通过 UI 更改按钮的背景颜色(您必须在 .cs 代码中编写主题调整代码)。此外,您的控件将在视觉上保持一致。
  • 虽然这是一项更大的任务,但我会在创建控件时牢记这一点。我有一些需要高对比度颜色的最终用户,所以我创建了一个主题和一些用于主题调整的代码。

编辑 - 更多信息

您不必为基本属性创建依赖属性(尽管我想如果您真的愿意的话,您可以这样做)。您可以在控件的代码隐藏中的 XAML 或 callbacks/events 中解决它们。

示例:围绕基本背景工作 属性。

public override void OnApplyTemplate()
{
    base.OnApplyTemplate();

    //  Set the default background
    DefaultBackground = this.Background;
}

//  Store the default background color to revert back to
private Brush DefaultBackground;

//  Dependency property for mouse over background color
public static readonly DependencyProperty MouseOverBackgroundProperty = DependencyProperty.Register(
    nameof(MouseOverBackground), typeof(Brush),
    typeof(NavButton), new PropertyMetadata(Brushes.Transparent));

public Brush MouseOverBackground
{
    get => (Brush)GetValue(MouseOverBackgroundProperty);
    set => SetValue(MouseOverBackgroundProperty, value);
}

// On Mouse Enter => Set Background
protected override void OnMouseEnter(MouseEventArgs e)
{
    base.OnMouseEnter(e);

    //  Set background color
    this.Background = MouseOverBackground;
}

// On Mouse Leave => Revert Background
protected override void OnMouseLeave(MouseEventArgs e)
{
    base.OnMouseLeave(e);

    //  Set background color back
    this.Background = DefaultBackground;
}

我使用控件中已有的事件来处理背景颜色状态。这是一个使用事件处理程序覆盖的基本示例,但您可以直接订阅事件。

然后您的 XAML 将如下所示:

<local:NavButton Background="Transparent" MouseOverBackground="Red"/>       

<!-- OR -->

<SolidColorBrush x:Key="ButtonBackground" Color="#1AFFFFFF" />
<SolidColorBrush x:Key="ButtonMouseOverBackground" Color="#00897B" />

<local:NavButton Background="{DynamicResource ButtonBackground}" 
     MouseOverBackground="{DynamicResource ButtonMouseOverBackground}"/>        


触发器在代码隐藏中处理。


编辑 2:更多信息

我忘了说除非您设置了默认值,否则触发器可能无法工作。您在 Style.

中设置默认值
<Style TargetType="{x:Type local:NavButton}">
    <!-- The default value -->
    <Setter Property="Background" Value="Grey" />
            
    <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <!-- The trigger value -->
            <Setter Property="Backround" Value="Red" />
        </Trigger>
    </Style.Triggers>
</Style>