如果我创建这样的自定义控件:
public class MyControl : ContentControl
{
public static readonly DependencyProperty ItemsProperty =
DependencyProperty.Register(
"Items",
typeof(ObservableCollection<object>),
typeof(MyControl),
new PropertyMetadata(null));
public MyControl()
{
// Setup a default value to empty collection
// so users of MyControl can call MyControl.Items.Add()
Items = new ObservableCollection<object>();
}
public ObservableCollection<object> Items
{
get { return (ObservableCollection<object>)GetValue(ItemsProperty); }
set { SetValue(ItemsProperty, value); }
}
}
然后允许用户在Xaml中绑定它,如下所示:
<DataTemplate>
<MyControl Items="{Binding ItemsOnViewModel}"/>
</DataTemplate>
然后绑定永远不会起作用!这是由于Dependency Property Precedence,它将CLR Set值置于模板绑定之上!
所以,我理解为什么这不起作用,但我想知道是否有解决方案。是否可以为MyControl的懒惰使用者提供一个默认值ItemsProperty,以便以编程方式添加Items,同时允许My Control的MVVM高级用户通过DataTemplate绑定到同一属性?
这适用于Silverlight&amp; WPF。一个样式的DynamicResource setter似乎是一个解决方案,但对Silverlight不起作用:(
更新:
我可以确认 SetCurrentValue(ItemsProperty, new ObservableCollection<object>());
完全符合我的要求 - 在WPF中。它写入默认值,但可以通过模板绑定覆盖它。 任何人都可以建议Silverlight等效吗?说起来容易做起来难! :■
另一个更新:
显然,您可以使用值强制模拟.NET3.5中的SetCurrentValue,并且可以使用这些技术在Silverlight中模拟值强制。也许这里有一个(冗长的)解决方法。
SetCurrentValue workaround for .NET3.5 using Value Coercion
Value Coercion workaround for Silverlight
答案 0 :(得分:0)
当ObservableCollection属性出现异常时,我会尝试抛弃该属性的赋值。我发现引用不能正确转换,绑定会以某种方式丢失。因此,我实际上避免了设置 ObservableCollection属性(相反,更喜欢清除现有属性并向其添加元素)。使用DependencyProperty变得真的草率,因为你将在你的setter中多次调用你的getter。您可能需要考虑使用INotifyPropertyChanged。无论如何,这就是它的样子:
编辑:Blatantly偷走了SteveL的回答。我重新设计了一下触摸,这样你只需要一次GetValue调用就可以了。好的工作。public ObservableCollection<object> Items
{
get
{
ObservableCollection<object> coll = (ObservableCollection<object>)GetValue(ItemsProperty);
if (coll == null)
{
coll = new ObservableCollection<object>();
this.SetValue(ItemsProperty, coll);
}
return coll;
}
set
{
ObservableCollection<object> coll = Items;
coll.Clear();
foreach(var item in value)
coll.Add(item);
}
}
请注意,这取决于您的默认设置是否正确。这意味着将静态ItemsProperty默认更改为正确类型的新ObservableCollection(即新的PropertyMetadata(new ObservableCollection())。您还必须在构造函数中删除该setter。并注意,我不知道是否实际上会工作。如果没有,你肯定会转而使用INotifyPropertyChanged ......
答案 1 :(得分:0)
您不能只指定依赖项属性的默认属性:
public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register(
"Items",
typeof(ObservableCollection<object>),
typeof(CaseDetailControl),
new PropertyMetadata(new ObservableCollection<object>()));
或者我错过了你的目标?
编辑:
啊......在那种情况下如何在getter上检查null?:
public ObservableCollection<object> Items
{
get
{
if ((ObservableCollection<object>)GetValue(ItemsProperty) == null)
{
this.SetValue(ItemsProperty, new ObservableCollection<object>());
}
return (ObservableCollection<object>)GetValue(ItemsProperty);
}
set
{
this.SetValue(ItemsProperty, value);
}
}