Listen to Changes of Dependency Property

Listen to changes of dependency property

If it's a DependencyProperty of a separate class, the easiest way is to bind a value to it, and listen to changes on that value.

If the DP is one you're implementing in your own class, then you can register a PropertyChangedCallback when you create the DependencyProperty. You can use this to listen to changes of the property.

If you're working with a subclass, you can use OverrideMetadata to add your own PropertyChangedCallback to the DP that will get called instead of any original one.

How do I listen to changes in Dependency properties from within an attached dependency property?

You can create a PropertyChangeNotifier class as described in this blog post

After you create it you can use it on attached properties like this:

ListBox listbox = new ListBox();
...
PropertyChangeNotifier notifier = new PropertyChangeNotifier(listBox, “(Grid).Row”);
notifier.ValueChanged += new EventHandler(OnValueChanged);

Also, DependencyPropertyDescriptor doesn't exists in .net 4.5 client profile. However, it does exist in the normal profile. So if you must have it just change the target framework of your project.

Listen to DependencyProperty changed event and get the old value

Unfortunately, you don't get old value information when registering property changed event handler this way.

One workaround is to store property value somewhere (this is your 'old' value) and then compare it to current value in the event handler.

Another workaround is to create your own dependency property (DP) and create binding between your DP and the control's DP. This will give you change notification in the WPF style.

Here is an article about this.

Property Changed in DependencyProperty

When you add an item to the ChartEntries collection, you do not actually change that property, so the PropertyChangedCallback isn't called. In order to get notified about changes in the collection, you need to register an additional CollectionChanged event handler:

private static void OnChartEntriesChanged(
DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
var chartView = (ChartView)obj;
var oldCollection = e.OldValue as INotifyCollectionChanged;
var newCollection = e.NewValue as INotifyCollectionChanged;

if (oldCollection != null)
{
oldCollection.CollectionChanged -= chartView.OnChartEntriesCollectionChanged;
}

if (newCollection != null)
{
newCollection.CollectionChanged += chartView.OnChartEntriesCollectionChanged;
}
}

private void OnChartEntriesCollectionChanged(
object sender, NotifyCollectionChangedEventArgs e)
{
...
}

It would also make sense not to use ObservableCollection<ChartEntry> for the property type, but simply ICollection or IEnumerable instead. This would allow for other implementations of INotifyCollectionChanged in the concrete collection type. See here and here for more information.

How to subscribe to change DependencyProperty?

Here is one way of doing it, using the handy DependencyPropertyDescriptor class.

 var pd = DependencyPropertyDescriptor.FromProperty(TextBox.TextProperty, typeof(TextBox));
pd.AddValueChanged(myTextBox, OnTextChanged);

private void OnTextChanged(object sender, EventArgs e)
{
...
}

How To Raise Property Changed events on a Dependency Property?


  1. Implement INotifyPropertyChanged in your class.

  2. Specify a callback in the property metadata when you register the dependency property.

  3. In the callback, raise the PropertyChanged event.

Adding the callback:

public static DependencyProperty FirstProperty = DependencyProperty.Register(
"First",
typeof(string),
typeof(MyType),
new FrameworkPropertyMetadata(
false,
new PropertyChangedCallback(OnFirstPropertyChanged)));

Raising PropertyChanged in the callback:

private static void OnFirstPropertyChanged(
DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
PropertyChangedEventHandler h = PropertyChanged;
if (h != null)
{
h(sender, new PropertyChangedEventArgs("Second"));
}
}

Listening to dependency property changes on one viewmodel from another viewmodel

For your class CustomerViewModel I can see only fields of type string in it, so you can use MemberwiseClone() method to create a clone object for CustomerViewModel.

public class CustomerViewModel
{
.....

public CutomerViewModel Clone()
{
return (CustomerViewModel)MemberwiseClone();
}

.....
}

And in your MainWindowViewModel when Being Shipped checkBox get checked:

ShippedCustomer = BilledCustomer.Clone();

Dependency Property on a user control not updating the property when bound data changes


The setter has a console trace that never fires so I am confident that the property is never being set.

This is a trap. The property getters and setters you have defined are for your convenience. The WPF Framework will not call them, it will use the dependency property directly. Never do anything in those getters and setters that you need to get done.

If you want to react to property changes, use the callback you already discovered. Your console trace should be in there, not in the setter.



Related Topics



Leave a reply



Submit