Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DependencyProperties not firing callbacks as expected in UserControl

I have a very simple example of a DependencyProperty I've registered on a UserControl which is not quite working as expected.

I am binding this property to a DP (called Test) in MainWindow which seems to be firing the OnPropertyChanged events every time it is changed, but the DependencyProperty in my UserControl that is the target of this binding only seems to get notified the first time this property is changed.

Here is what I'm trying to do in code:

My UserControl:

public partial class UserControl1 : UserControl
{
    public static readonly DependencyProperty ShowCategoriesProperty = 
        DependencyProperty.Register("ShowCategories", typeof(bool), typeof(UserControl1), new FrameworkPropertyMetadata(false, OnShowsCategoriesChanged));

    public UserControl1()
    {
        InitializeComponent();
    }

    public bool ShowCategories
    {
        get
        {
            return (bool)GetValue(ShowCategoriesProperty);
        }
        set
        {
            SetValue(ShowCategoriesProperty, value);
        }
    }

    private static void OnShowsCategoriesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        //this callback is only ever hit once when I expect 3 hits...

        ((UserControl1)d).ShowCategories = (bool)e.NewValue;
    }
}

MainWindow.xaml.cs

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();

        Test = true;  //this call changes default value of our DP and OnShowsCategoriesChanged is called correctly in my UserControl

        Test = false;  //these following calls do nothing!! (here is where my issue is)
        Test = true;
    }

    private bool test;
    public bool Test
    {
        get { return test; }
        set
        {
            test = value;
            OnPropertyChanged("Test");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string property)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(property));
        }
    }
}

MainWindow.xaml

<Window x:Class="Binding.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:uc="clr-namespace:Binding"
    DataContext="{Binding RelativeSource={RelativeSource Self}}"        
    Title="MainWindow" Height="350" Width="525">
  <Grid>
    <uc:UserControl1 ShowCategories="{Binding Test}" />
  </Grid>
</Window>
like image 922
genus Avatar asked Oct 08 '12 16:10

genus


1 Answers

The problem is that you're setting the ShowCategories value to itself:

((UserControl1)d).ShowCategories = (bool)e.NewValue;

This line is useless, since the value of ShowCategories has already been modified. That's why you're in the property changed callback in the first place. At first glance, this could be seen as a no-op: after all, you're simply setting a property value to its current value, which in WPF doesn't raise any change.

However, since the binding isn't two-way, changing the property value overwrites the binding. That's why there is no more callback raised. Simply remove the assignment in the callback and you're done.

like image 80
Julien Lebosquain Avatar answered Sep 30 '22 14:09

Julien Lebosquain