Dev Logging

printf("does this work\n");
in

Debugging Dependency Properties in WPF: Addendum

This is going to be a pretty brief post. I just wanted to mention a small addition to the data binding debugging solution I posted about last time. When we left off, we had a pretty decent solution to debugging via a property changed callback. And here it is:

   1:  public static PropertyChangedCallback PrintfDebugger
   2:      (PropertyChangedCallback propertyChangedCallback)
   3:  {
   4:      return (d, e) =>
   5:      {
   6:          propertyChangedCallback(d, e);
   7:          Console.WriteLine("{0}.{1}: {2}",
   8:              d.DependencyObjectType.Name,
   9:              e.Property.Name,
  10:              e.NewValue);
  11:      };
  12:  }

This works fine, but it's slightly limited. One common scenario where this might not be so useful is if you have several of the same type of control on the same page. This would make it pretty difficult to tell which control is actually receiving the update. What can we do? Well, we can mitigate this by using the name of the element, if it exists.

   1:  public static PropertyChangedCallback PrintfDebugger
   2:      (PropertyChangedCallback propertyChangedCallback)
   3:  {
   4:      return (d, e) =>
   5:      {
   6:          propertyChangedCallback(d, e);
   7:          var elem = d as FrameworkElement;
   8:          string name = elem != null && !string.IsNullOrEmpty(elem.Name) ? 
   9:              elem.Name : 
  10:              d.DependencyObjectType.Name;
  11:          Console.WriteLine("{0}.{1}: {2}",
  12:              name,
  13:              e.Property.Name,
  14:              e.NewValue);
  15:      };
  16:  }

Here we check to see if the dependency object is a FrameworkElement. If it is, and it has a name, we use that. Otherwise, we default to the class name. Note that there are other classes that implement a Name property, but, for the sake of simplicity, I've restricted this to what I believe is the most common scenario. Now, let's see it in action. First, we'll confirm that it still works in our previous case by leaving the control unnamed, like so:

   1:  <Grid>
   2:      <local:MyUserControl MyProperty="{Binding ActualWidth, ElementName=root}"/>
   3:  </Grid>

And running it yields the desired result:

image

Now, let's add a second named control with the same binding.

   1:  <Grid>
   2:      <local:MyUserControl MyProperty="{Binding ActualWidth, ElementName=root}"/>
   3:      <local:MyUserControl x:Name="newControl" MyProperty="{Binding ActualWidth, ElementName=root}"/>
   4:  </Grid>

And the moment of truth:

image

Nice.

Comments

Ancora Imparo said:

In my last couple posts , I&#39;ve highlighted a way to inject debugging into dependency properties updated

# January 25, 2009 6:48 PM