Detecting a changed DataContext

A colleague showed me a great and simple solution for a problem: finding out when the DataContext of a Silverlight control changes.

Let’s say a details form is bound against a Dog object. To the left of the form there is a list of dogs, when the user clicks a Widget in the list, the DataContext of the form is set.

The form contains a control for picking the name of the dog. This is a special control: when the user has modified the dog name, its background is set to yellow.
The when writing this control is that you can monitor changes on the Text property, and then turn the control’s background to yellow when it changes. The challenge is how to reset the background color. We need to determine if a change comes from manipulating the value, or from changing the dog in the list, i.e. the form’s DataContext.

It’s not possible to directly watch the DataContext; there is no event for that.

Here’s the solution that my colleague found: declare a new DependencyProperty that does nothing more than execute a PropertyChangedCallback when its value changes. And then, bind this property directly against the control’s DataContext. OK, if someone assigns a value or a binding or a value to that property in XAML code, the mechanism breaks, but that’s what we’ve got comments for.

using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

namespace GreenIcicle.DetectDataContextChange
{
  public class DogNameTextBox : Control
  {
    // Constructor
    public DogNameTextBox()
    {
      // Bind a DependencyProperty against
      // the DataContecxt of the control.
      // Since no path is specified, the DataContext
      // itself is bound.
      SetBinding(DataContextWatcherProperty, new Binding());
    }

    // In this method, add the payload logic that is called
    // whenever the DataContext of the control changes.
    protected virtual void ResetControlState()
    {
      // Reset the control's state
    }

    // Dependency property that is bound against the DataContext.
    // When its value (i.e. the control's DataContext) changes,
    // call DataContextWatcher_Changed.
    public static DependencyProperty DataContextWatcherProperty = DependencyProperty.Register(
      "DataContextWatcher",
      typeof(object),
      typeof(DogNameTextBox),
      new PropertyMetadata(DataContextWatcher_Changed));

    // Called when the control's DataContext changes.
    public static void DataContextWatcher_Changed(
      DependencyObject sender,
      DependencyPropertyChangedEventArgs args)
    {
      // Call ResetControlState on the control of which
      // the DataContext has been changed.
      DogNameTextBox senderControl = sender as DogNameTextBox;
      if (senderControl != null)
      {
        senderControl.ResetControlState();
      }
    }
  }
}

Thanks to Andreas/Raphael for finding this out!

Advertisements
About

Christian is a software architect/developer. He lives in Germany, reads a lot, and likes cycling.

Tagged with:
Posted in Coding

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: