我正在使用一个自定义控件,其中包含多个用户定义的依赖属性。我遇到了与这个问题描述相同的问题。
我的控件在构造函数中设置自定义依赖属性的默认值。当我在中使用控件时,即使我尝试在XAML中设置它,也始终使用在构造函数中设置的值。
链接问题的答案解释说,C#代码中设置的值具有更高的优先级,更好的方法是在依赖属性的元数据中指定默认值。
在我的情况下,我无法指定默认值,因为依赖属性没有适用于所有情况的单个默认值。默认值取决于另一个属性,因此必须在创建控件时查找它们,而不是在注册属性时查找它们。
以下是一些代码,以帮助说明我的问题:
XAML的用法大致如下:
总结一下:
期望的行为是首先使用XAML中的值。如果在XAML中没有指定该值,则希望回退到控件构造函数中设置的默认值。
如果我直接在视图中包含控件,则会得到预期的行为。如果该控件在DataTemplate中使用,则始终会得到构造函数中设置的默认值(即使数据模板明确设置了其他值)。
是否有其他方法可以在模板中使用控件时指定默认值?我能想到的唯一选择是将控件分成几个类似但不同的控件,每个控件都使用注册到依赖属性的默认值(这样就不需要基于Mode属性设置默认值)。
我的控件在构造函数中设置自定义依赖属性的默认值。当我在中使用控件时,即使我尝试在XAML中设置它,也始终使用在构造函数中设置的值。
链接问题的答案解释说,C#代码中设置的值具有更高的优先级,更好的方法是在依赖属性的元数据中指定默认值。
在我的情况下,我无法指定默认值,因为依赖属性没有适用于所有情况的单个默认值。默认值取决于另一个属性,因此必须在创建控件时查找它们,而不是在注册属性时查找它们。
以下是一些代码,以帮助说明我的问题:
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的用法大致如下:
<!-- 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属性设置默认值)。
<local:MyControl MyProperty="4" />
如果这是唯一应该设置属性的方式,而且永远不会使用绑定(请参见我的编辑),那么你就不必担心,尽管覆盖绑定并不被认为是一种好的做法。 - Adi LesterMyProperty = 42;
会破坏任何绑定。如果我正在使用像您在编辑中添加的绑定,只要绑定未计算为MyProperty.DefaultMetadata.DefaultValue
,那么就不会调用该值并且绑定不会被破坏,对吗?您能详细说明一下只读属性的推荐解决方案吗?我不确定我是否理解了。 - zmb