使用 ControlTemplate 在用户控件上绑定自定义依赖属性

Posted

技术标签:

【中文标题】使用 ControlTemplate 在用户控件上绑定自定义依赖属性【英文标题】:Binding custom Dependency Property on User Control with ControlTemplate 【发布时间】:2019-06-17 17:13:55 【问题描述】:

我创建了一个带有ControlTemplate 的自定义按钮。 我使用了ControlTemplate 来绑定UserControl 的默认属性,例如BackgroundForeground

但是,如果我添加自定义依赖属性(例如 CornerRadius),我会收到两个错误:

    “成员 'CornerRadius' 无法识别或无法访问。” “在类型 'UserControl' 上找不到静态成员 'CornerRadiusProperty'。”

Xaml:

<UserControl x:Class="MyProject.MyButton"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         mc:Ignorable="d" 
         d:DesignHeight="50" d:DesignWidth="50"
         BorderThickness="1" BorderBrush="White" Background="Black"
         Content="OK" Foreground="White">
    <UserControl.Template>
        <ControlTemplate TargetType="UserControl">
            <Border Name="ground"
                    BorderThickness="TemplateBinding BorderThickness"
                    BorderBrush="TemplateBinding BorderBrush"
                    Background="TemplateBinding Background"
                    CornerRadius="TemplateBinding CornerRadius">
                <Label Name="content"
                       VerticalContentAlignment="Center" 
                       HorizontalContentAlignment="Center"
                       Content="TemplateBinding Content"
                       Foreground="TemplateBinding Foreground"
                       FontFamily="TemplateBinding FontFamily"
                       FontWeight="TemplateBinding FontWeight"
                       FontSize="TemplateBinding FontSize"/>
            </Border>
        </ControlTemplate>
    </UserControl.Template>
</UserControl>

背后的代码:

namespace MyProject

    public partial class MyButton : UserControl
    
        public static readonly DependencyProperty CornerRadiusProperty =
            DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(MyButton));

        public CornerRadius CornerRadius
        
            get => (CornerRadius)GetValue(CornerRadiusProperty);
            set => SetValue(CornerRadiusProperty, value);
        


        public MyButton() => InitializeComponent();
    

如果我使用这里指定的解决方案User control with custom properties 我会遇到这个问题Wpf - Custom control: How to override default properties?。

那么,有什么办法可以避免这两个问题呢?

【问题讨论】:

您的TargetTypeControlTemplate 不正确。它应该是 MyButton。 我添加了 xmlns:local="clr-namespace:MyProject" 和 TargetType="local:MyButton" 但现在它显示“ArgumentException: 'MyButton' ControlTemplate TargetType 与模板类型 'UserControl' 不匹配。 " 更新:ArgumentException: 'MyButton' ControlTemplate TargetType does not match templated type 'UserControl'. 似乎只是编辑器的渲染问题。当我构建我的应用程序并运行它时,它可以正常工作:user-images.githubusercontent.com/32025549/… Strange... 【参考方案1】:

自定义 Button 不应该是 UserControl,而是直接派生自 Button。

为您的 Visual Studio 项目添加一个“自定义控件 (WPF)”,并像这样修改它:

public class MyButton : Button

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

    public static readonly DependencyProperty CornerRadiusProperty =
        DependencyProperty.Register(
            nameof(CornerRadius), typeof(CornerRadius), typeof(MyButton));

    public CornerRadius CornerRadius
    
        get => (CornerRadius)GetValue(CornerRadiusProperty);
        set => SetValue(CornerRadiusProperty, value);
    

然后在生成的Themes\Generic.xaml文件中更改其默认样式:

<Style TargetType="local:MyButton">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:MyButton">
                <Border Name="ground"
                        BorderThickness="TemplateBinding BorderThickness"
                        BorderBrush="TemplateBinding BorderBrush"
                        Background="TemplateBinding Background"
                        CornerRadius="TemplateBinding CornerRadius">
                    <Label Name="content"
                           VerticalContentAlignment="Center" 
                           HorizontalContentAlignment="Center"
                           Content="TemplateBinding Content"
                           Foreground="TemplateBinding Foreground"
                           FontFamily="TemplateBinding FontFamily"
                           FontWeight="TemplateBinding FontWeight"
                           FontSize="TemplateBinding FontSize"/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

详情请见Control Authoring Overview。

【讨论】:

以上是关于使用 ControlTemplate 在用户控件上绑定自定义依赖属性的主要内容,如果未能解决你的问题,请参考以下文章

[WPF自定义控件库] 自定义控件的代码如何与ControlTemplate交互

WPF ControlTemplate

DataTemplate 和 ControlTemplate 详细应用

Xamarin XAML语言教程构建ControlTemplate控件模板

WPF ControlTemplate简介

Xamarin XAML语言教程构建ControlTemplate控件模板