1

如果我创建这样的自定义控件:

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 的懒惰消费者提供新的 ObservableCollection 的 ItemsProperty 的默认值,同时允许 My Control 的 MVVM 高级用户通过 DataTemplate 绑定到相同的属性?

这适用于 Silverlight 和 WPF。风格的 DynamicResource 设置器似乎是一个解决方案,但这不适用于 Silverlight :(

更新:

我可以确认SetCurrentValue(ItemsProperty, new ObservableCollection<object>());完全符合我的要求 - 在 WPF 中。它写入默认值,但它可以被模板绑定覆盖。任何人都可以建议一个等效的 Silverlight 吗?说起来容易做起来难!:秒

另一个更新:

显然,您可以使用值强制在 .NET3.5 中模拟 SetCurrentValue,并且可以使用这些技术在 Silverlight 中模拟值强制。也许这里有一个(冗长的)解决方法。

.NET3.5 的 SetCurrentValue 解决方法,使用Silverlight 的 Value Coercion Value Coercion workaround

4

2 回答 2

0

当 ObservableCollection 属性出现异常时,我尝试丢弃对该属性的分配。我发现参考文献翻译不正确,绑定丢失了,不知何故。因此,我避免实际设置ObservableCollection 属性(而是更喜欢清除现有属性并向其添加元素)。使用 DependencyProperty会变得非常草率,因为您将在 setter 中多次调用 getter。您可能要考虑改用 INotifyPropertyChanged。无论如何,这就是它的样子:

编辑:公然从 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(即 new PropertyMetadata(new ObservableCollection())。您还必须在构造函数中删除该设置器。注意,我不知道是否这样'实际上会工作。如果没有,你肯定会想要使用 INotifyPropertyChanged ......

于 2012-11-01T17:28:28.053 回答
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);
        }
    }
于 2012-11-01T17:37:32.563 回答