Ryszard Dżegan
Ryszard Dżegan

Reputation: 25414

Standard property works, but dependency property doesn't in WPF

I have the following code behind, which works:

public DataTemplate ItemTemplate
{
    get { return _list.ItemTemplate; }
    set { _list.ItemTemplate = value; }
}

And I have the code, that I want to have, but it doesn't work. Even setter is never invoked:

public static readonly DependencyProperty ItemTemplateProperty = DependencyProperty.Register("ItemTemplate", typeof(DataTemplate), typeof(MyUserControl));
public DataTemplate ItemTemplate
{
    get { return (DataTemplate)GetValue(ItemTemplateProperty); }
    set
    {
        _list.ItemTemplate = value;
        SetValue(ItemTemplateProperty, value);
    }
}

The use of that is in XAML:

<Window.Resources>
    <DataTemplate x:Key="ItemTemplate">
        <TextBlock Text="{Binding Path=Name}"/>
    </DataTemplate>
</Window.Resources>

<local:MyUserControl ItemTemplate="{StaticResource ItemTemplate}"/>

Why the standard property works and dependency property doesn't?

Upvotes: 7

Views: 857

Answers (2)

Akash Kava
Akash Kava

Reputation: 39916

DependencyProperty never invokes "Set" method, instead you will have to look for PropertyChanged event handler within creation of dependency property statement.

public static readonly DependencyProperty ItemTemplateProperty = 
   DependencyProperty.Register(
        "ItemTemplate", 
         typeof(DataTemplate), 
         typeof(MyUserControl),
         new FrameworkPropertyMetadata( 
             null, 
             new PropertyChangedCallback(ItemTemplateChanged) ));
public DataTemplate ItemTemplate
{
    get { return (DataTemplate)GetValue(ItemTemplateProperty); }
    set
    {
        _list.ItemTemplate = value;
        SetValue(ItemTemplateProperty, value);
    }
}

public static void ItemTemplateChanged(
   DependencyObject sender, 
   DependencyPropertyChangedEventArgs e){
   ((MyUserControl)sender).OnItemTemplateChanged(e);
}

protected void OnItemTemplateChanged(DependencyPropertyChangedEventArgs e){
    // you write your code here..
}

Upvotes: 2

Tim S.
Tim S.

Reputation: 56536

With the dependency property, .Net is doing something that's not obvious: it's accessing the dependency property identified by ItemTemplateProperty directly instead of using the get and set methods that you declared. The only difference, in this case, is that your _list.ItemTemplate = value; is never run.

When you use dependency properties, your getters and setters should only contain the usual things. Anything else will end up being confusing because WPF bypasses them when it uses the property.

If you need to set _list.ItemTemplate to the value, you should attach a static PropertyChangedCallback using the other DependencyProperty.Register overload. E.g.

private static void OnItemTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
    var uc = (MyUserControl)d;
    uc._list.ItemTemplate = (DataTemplate)e.NewValue;
}

Upvotes: 7

Related Questions