Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
392 views
in Technique[技术] by (71.8m points)

silverlight - WPF dependency property precedence & reference type Default Values

If I create a custom control like this:

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); } 
   } 
}

And then allow the user to bind to it in Xaml like this:

<DataTemplate>
    <MyControl Items="{Binding ItemsOnViewModel}"/>
</DataTemplate>

Then the binding never works! This is due to the Dependency Property Precedence, which puts CLR Set values above Template bindings!

So, I understand why this isn't working, but I wonder if there is a solution. Is it possible to provide a default value of ItemsProperty to new ObservableCollection for lazy consumers of MyControl that just want to add Items programmatically, while allowing MVVM power-users of My Control to bind to the same property via a DataTemplate?

This is for Silverlight & WPF. DynamicResource setter in a style seemed like a solution but that won't work for Silverlight :(

Update:

I can confirm SetCurrentValue(ItemsProperty, new ObservableCollection<object>()); does exactly what I want - in WPF. It writes the default value, but it can be overridden by template-bindings. Can anyone suggest a Silverlight equivalent? Easier said than done! :s

Another Update:

Apparently you can simulate SetCurrentValue in .NET3.5 using value coercion, and you can simulate value coercion in Silverlight using these techniques. Perhaps there is a (long-winded) workaround here.

SetCurrentValue workaround for .NET3.5 using Value Coercion
Value Coercion workaround for Silverlight

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Can't you just specify the default property of the dependency property:

  public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register(
        "Items",
        typeof(ObservableCollection<object>),
        typeof(CaseDetailControl),
        new PropertyMetadata(new ObservableCollection<object>()));

or am I missing what you are after?

Edit:

ah... in that case how about checking for null on the getter?:

    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);
        }
    }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...