如何为模板控件创建自定义属性

时间:2017-02-03 20:46:04

标签: c# xaml uwp

我有一个模板控件,它有一个StackPanel作为root。我想要的是一种制作这样的东西的方法:

<Controls:MyControl Kind="SomeKind"/>

基于SomeKind,StackPanel的背景会发生变化。例如,“Kinds”的数量有限,与Button中的Horizo​​ntalAlignments数量有限的方式相同。

<Button HorizontalAlignment="Center"/>

我在互联网上搜索了一下,看起来它似乎涉及附加属性,但我还没有找到一个干净,简单易用的UWP示例。我找到了一些WPF的例子,但它们似乎没有用。

2 个答案:

答案 0 :(得分:3)

不,您不需要附加属性,因为它可能只与您的自定义控件关联。您需要的是enum类型的依赖属性

假设你有这个enum -

public enum PanelBackgroundType
{
    Orange,
    Pink,
    Offwhite
}

然后你的依赖属性看起来像这样 -

public PanelBackgroundType PanelBackgroundType
{
    get { return (PanelBackgroundType)GetValue(PanelBackgroundTypeProperty); }
    set { SetValue(PanelBackgroundTypeProperty, value); }
}

// Using a DependencyProperty as the backing store for PanelBackgroundType.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty PanelBackgroundTypeProperty =
    DependencyProperty.Register("PanelBackgroundType", typeof(PanelBackgroundType), typeof(MyControl), 
    new PropertyMetadata(PanelBackgroundType.Offwhite, (s, e) =>
    {
        if ((PanelBackgroundType)e.NewValue != (PanelBackgroundType)e.OldValue)
        {
            // value really changed, invoke your changed logic here
            var control = (MyControl)s;

            switch ((PanelBackgroundType)(e.NewValue))
            {
                case PanelBackgroundType.Orange:
                    control.MyStackPanel.Background = new SolidColorBrush(Colors.Orange);
                    break;
                case PanelBackgroundType.Pink:
                    control.MyStackPanel.Background = new SolidColorBrush(Colors.Pink);
                    break;
                case PanelBackgroundType.Offwhite:
                default:
                    control.MyStackPanel.Background = new SolidColorBrush(Colors.Wheat);
                    break;
            }
        }
        else
        {
            // else this was invoked because of boxing, do nothing
        }
    }));

请注意,我在属性更改回调中检查了(PanelBackgroundType)e.NewValue != (PanelBackgroundType)e.OldValue,以查看dp的值是否确实已更改。这似乎是多余的,但根据MSDN,这是最好的做法 -

  

如果DependencyProperty的类型是枚举或结构,   即使内部值,也可以调用回调   结构或枚举值没有改变。这是不同的   来自系统原语,例如字符串,只有在调用时才会调用   价值改变了。这是box和unbox操作的副作用   这些在内部完成的值。如果你有   PropertyChangedCallback方法,用于属性值为的属性   枚举或结构,你需要比较OldValue和   NewValue通过自己转换值并使用重载   现在投射值可用的比较运算符。或者如果   没有这样的运营商(可能是自定义的情况)   结构),您可能需要比较各个值。你会   如果结果是值,则通常选择不执行任何操作   没有改变。

答案 1 :(得分:0)

请看一下这个链接:https://msdn.microsoft.com/en-us/windows/uwp/xaml-platform/custom-dependency-properties

它将向您展示如何为您可以在UI中编辑的对象添加自定义依赖项属性。

虽然我建议您查看Microsoft的文档,但我会给您一个快速举例说明您想要的内容

public sealed partial class MyControl : UserControl
{
    public MyControl()
    {
        this.InitializeComponent();
    }

    public static readonly DependencyProperty KindProperty = DependencyProperty.Register(
    "Kind", typeof(string), typeof(MyControl),
    new PropertyMetadata(null, new PropertyChangedCallback(OnKindChanged)));

    public string Kind
    {
        get { return (string)GetValue(KindProperty); }
        set { SetValue(KindProperty, value); }
    }

    private static void OnKindChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        // Executed method when the KindProperty is changed
    }
}