locked
How to catch PropertyChanged events RRS feed

  • Question

  • I'm creating a user control and I've created a data class for the data that my control needs.  This data class implements INotifyPropertyChanged and it gets bound to the control's DataContext.  Some of the data gets bound to controls defined in XAML.  That works beautifully.  When the data changes, the user control recognizes those changes.

     

    For certain data changes, I want to catch the value change in code and do some processing.  How do I listen to the PropertyChanged notifications from the data class?

     

    Sunday, August 26, 2007 6:19 AM

Answers

  •  

    If you're doing this purely in code and you know that the data class implements INotifyPropertyChanged, you don't need to use a binding at all.  You can simply set a handler on the PropertyChanged event for the data class.  This works like any other managed event.  When your handler is called, you simply look at the PropertyName member of the PropertyChangedEventArgs and take the appropriate action:

     

    Code Snippet

    private void OnDataPropertyChanged(object sender, PropertyChangedEventArgs e)

    {

        switch (e.PropertyName)

        {

            case "IsEditModeEnabled":

            InitializeControlForEditMode();

            break;

        }

    }

     

    As for when you establish the handler, you can override the metadata for the DataContextProperty DP on your user control to add a property changed handler.  This will give your control an opportunity to establish the handler when the data context is first set (and also if it changes) at runtime.

     

    Code Snippet

    static MyUserControl()

    {

        DataContextProperty.OverrideMetadata(typeof(MyUserControl),

            new FrameworkPropertyMetadata(new PropertyChangedCallback(OnDataContextChanged)));

    }

     

    private void OnDataContextChanged(DependencyPropertyChangedEventArgs e)

    {

        if (e.OldValue != null)

        {

            if (e.OldValue is INotifyPropertyChanged)

            {

                (e.OldValue as INotifyPropertyChanged).PropertyChanged

                    -= new PropertyChangedEventHandler(OnDataPropertyChanged);

            }

        }

     

        if (e.NewValue != null)

        {

            if (e.NewValue is INotifyPropertyChanged)

            {

                (e.NewValue as INotifyPropertyChanged).PropertyChanged

                    += new PropertyChangedEventHandler(OnDataPropertyChanged);

            }

        }

    }

     

    Since a delegate represents a strong reference to the data object, you should also clear the handler when your control is unloaded, just to ensure the data object can be GC'd.

     

    Hope this helps!

    Sunday, August 26, 2007 8:21 AM

All replies

  • Hello, I think you can use Binding.SourceUpdated event to get the notification from data. Please check here for more information.

    Sunday, August 26, 2007 6:27 AM
  •  

    If you're doing this purely in code and you know that the data class implements INotifyPropertyChanged, you don't need to use a binding at all.  You can simply set a handler on the PropertyChanged event for the data class.  This works like any other managed event.  When your handler is called, you simply look at the PropertyName member of the PropertyChangedEventArgs and take the appropriate action:

     

    Code Snippet

    private void OnDataPropertyChanged(object sender, PropertyChangedEventArgs e)

    {

        switch (e.PropertyName)

        {

            case "IsEditModeEnabled":

            InitializeControlForEditMode();

            break;

        }

    }

     

    As for when you establish the handler, you can override the metadata for the DataContextProperty DP on your user control to add a property changed handler.  This will give your control an opportunity to establish the handler when the data context is first set (and also if it changes) at runtime.

     

    Code Snippet

    static MyUserControl()

    {

        DataContextProperty.OverrideMetadata(typeof(MyUserControl),

            new FrameworkPropertyMetadata(new PropertyChangedCallback(OnDataContextChanged)));

    }

     

    private void OnDataContextChanged(DependencyPropertyChangedEventArgs e)

    {

        if (e.OldValue != null)

        {

            if (e.OldValue is INotifyPropertyChanged)

            {

                (e.OldValue as INotifyPropertyChanged).PropertyChanged

                    -= new PropertyChangedEventHandler(OnDataPropertyChanged);

            }

        }

     

        if (e.NewValue != null)

        {

            if (e.NewValue is INotifyPropertyChanged)

            {

                (e.NewValue as INotifyPropertyChanged).PropertyChanged

                    += new PropertyChangedEventHandler(OnDataPropertyChanged);

            }

        }

    }

     

    Since a delegate represents a strong reference to the data object, you should also clear the handler when your control is unloaded, just to ensure the data object can be GC'd.

     

    Hope this helps!

    Sunday, August 26, 2007 8:21 AM
  • Yet another alternative would be to provide the Bindings on those properties which require special processing with a ValueConverter.  The ValueConverter can be used to perform certain types of processing, and in some situations provide a clean way to introduce such additional logic.

     

    Sunday, August 26, 2007 8:59 PM