首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >来自DataTemplate的自定义DataTemplate集

来自DataTemplate的自定义DataTemplate集
EN

Stack Overflow用户
提问于 2014-09-29 18:38:51
回答 1查看 2.4K关注 0票数 4

我正在使用一个具有多个用户定义的依赖项属性的自定义控件。我遇到了this question中描述的同样的问题。

我的控件是在其构造函数中设置自定义依赖项属性的默认值。当我在DataTemplate中使用控件时,总是使用构造函数中的值集,即使我试图在XAML中设置它。

链接问题的答案解释了C#代码中的值集具有更高的优先级,更好的方法是在依赖项属性的元数据中指定默认值。

在我的例子中,我不能指定默认值,因为依赖项属性没有一个适用于所有情况的默认值。默认值取决于另一个属性,因此必须在创建控件时查找它们,而不是在注册属性时查找它们。

下面是一些代码来帮助说明我的问题:

代码语言:javascript
复制
public partial class MyControl : UserControl
{
    public static readonly DependencyProperty MyProperty = 
            DependencyProperty.Register(
                "MyProperty",
                typeof(int),
                typeof(MyControl),
                new FrameworkPropertyMetadata(
                    int.MinValue,
                    FrameworkPropertyMetadataOptions.None,
                    new PropertyChangedCallback("OnMyPropertyChanged")));

    public MyControl() : base()
    {
        InitializeComponent();
        this.MyProperty = GetDefaultPropertyValue();
    }

    public int MyProperty
    {
        get { return (int)GetValue(MyProperty); }
        set { SetValue(MyProperty, value); }
    }

    private int GetDefaultPropertyValue()
    {
        // look up the appropriate default based on some other criteria
        return 42;

        // (in reality, the default value for "MyProperty"
        // depends on the value of a "Mode" custom DependencyProperty.
        // this is just hard coded for testing)
    }   
}

XAML用法如下所示:

代码语言:javascript
复制
<!-- View displays 4 (desired) -->
<local:MyControl MyProperty="4" />

<!-- View displays default of 42 (desired) -->
<local:MyControl />

<!-- View displays default of 42 (wanted 4) -->
<DataTemplate x:Key="MyTemplate">
    <local:MyControl MyProperty="4"/>
</DataTemplate>

概括地说:

所需的行为是首先使用来自XAML的值。如果该值没有在XAML中指定,那么我想回到控件的构造函数中设置的默认值。

如果我只是将控件直接包含在视图中,就会得到预期的行为。如果控件在DataTemplate中使用,那么我总是在构造函数中获得默认设置(即使数据模板显式地设置了另一个值)。

在模板中使用控件时,是否有其他方法来指定默认值?我能想到的唯一选项是将该控件拆分为几个单独但类似的控件,每个控件都使用一个使用依赖项属性注册的默认值(这消除了根据Mode属性设置默认值的需要)。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-09-29 19:01:46

OnApplyTemplate中设置默认值,同时添加一个小的检查,可以解决以下问题:

代码语言:javascript
复制
public override void OnApplyTemplate()
{
    base.OnApplyTemplate();

    // Only set the default value if no value is set.
    if (MyProperty == (int)MyPropertyProperty.DefaultMetadata.DefaultValue)
    {
        this.MyProperty = GetDefaultPropertyValue();
    }
}

请注意,虽然这是可行的,但这并不理想,因为通过代码设置属性值将基本上清除该属性的任何数据绑定。例如,在代码中调用MyProperty = 42后,以下绑定将不再工作:

代码语言:javascript
复制
<local:MyControl MyProperty="{Binding SomeProperty}" />

应该可以通过使用SetCurrentValue(MyPropertyProperty, GetDefaultPropertyValue());来修改属性而不是MyProperty = GetDefaultPropertyValue()来设置值,同时维护任何绑定,但我也不太喜欢这样做。

更好的解决办法

除了现有的只读属性之外,我要做的是引入一个新的只读属性,它将充当一个计算属性。例如:

代码语言:javascript
复制
private static readonly DependencyPropertyKey MyCalculatedPropertyPropertyKey =
    DependencyProperty.RegisterReadOnly("MyCalculatedProperty", typeof(int), typeof(MyControl),
    new PropertyMetadata(int.MinValue));

public static readonly DependencyProperty MyCalculatedPropertyProperty = MyCalculatedPropertyPropertyKey.DependencyProperty;

public int MyCalculatedProperty
{
    get { return (int)GetValue(MyCalculatedPropertyProperty); }
    private set { SetValue(MyCalculatedPropertyPropertyKey, value); }
}

private static void OnMyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    ((MyControl)d).MyCalculatedProperty = (int)e.NewValue;
}

public MyControl()
    : base()
{
    InitializeComponent();
    MyCalculatedProperty = GetDefaultPropertyValue();
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26106598

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档