Getting change notifications from any dependency property in Windows Store Apps
When declaring a dependency property, you can specify a callback to be called when the property changes. However if you want to be notified of changes of a property that is already declared, you have to rely on the class exposing an event for it (like TextChanged on the TextBox for the Text property). This event doesn't always exist. In WFP you could use the DependencyPropertyDescriptor class to register for change notifications of any property. In Silverlight and Windows Store Apps, this class doesn't exist. Fortunately, there is a little trick to achieve that: you need to declare your own dependency property, and add a change notification callback, then bind the property that you are really interested in to that property you just declared. When the property changes, the binding gets updated, your property (the one you declared) gets changed and the callback is triggered.
Here is a class that will do all of that for you:
public class DependencyPropertyWatcher<T> : DependencyObject, IDisposable
{
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register(
"Value",
typeof(object),
typeof(DependencyPropertyWatcher),
new PropertyMetadata(null, OnPropertyChanged));
public event EventHandler PropertyChanged;
public DependencyPropertyWatcher(DependencyObject target, string propertyPath)
{
this.Target = target;
BindingOperations.SetBinding(
this,
ValueProperty,
new Binding() { Source = target, Path = new PropertyPath(propertyPath), Mode = BindingMode.OneWay });
}
public DependencyObject Target { get; private set; }
public T Value
{
get { return (T)this.GetValue(ValueProperty); }
}
public static void OnPropertyChanged(object sender, DependencyPropertyChangedEventArgs args)
{
DependencyPropertyWatcher<T> source = (DependencyPropertyWatcher<T>)sender;
if (source.PropertyChanged != null)
{
source.PropertyChanged(source, EventArgs.Empty);
}
}
public void Dispose()
{
this.ClearValue(ValueProperty);
}
}
And here is how to use it:
private DependencyPropertyWatcher<string> watcher;
protected override void LoadState(Object navigationParameter, Dictionary pageState)
{
watcher = new DependencyPropertyWatcher<string>(this.textBox, "Text");
watcher.PropertyChanged += OnTextChanged;
}
private void OnTextChanged(object sender, EventArgs e)
{
var text = watcher.Value;
// ...
}