Showing posts with label Data Binding. Show all posts
Showing posts with label Data Binding. Show all posts

Thursday, April 23, 2009

Debugging Data Binding in WPF

What do you do when you suspect that a data binding is broken in your WPF application? Looking at the Output window for data binding exceptions can be helpful in many cases. However, there are cases where this does not help.

For example, below I have TextBox.Text bound to Slider.Value. But notice that the binding is OneWay.

<TextBox Text="{Binding ElementName=slider, Path=Value, Mode=OneWay}" Height="30" Width="100" Margin="10" />

<Slider Minimum="0" Maximum="100" Value="20" Margin="10" x:Name="slider" />

When I move the slider, the text in the TextBox shows the slider value as expected. Now I enter some text in the TextBox(which causes the binding to break since it is OneWay binding; but assume that I haven't realized that). I move the slider now, but the text in TextBox does not update. I suspect that the binding is broken. But how do I confirm that?

Simply looking at the Output Window in this case reveals nothing. What I've been doing until now is to add a dummy converter and set a break point in the Convert method. If the break point is not hit I know that the binding is broken. But that is really a long way of doing something that should be really done in a simpler way....

WPF 3.5 has a new property called PresentationTraceSources.TraceLevel that you can set on your data binding to get more detailed information on the binding in the Output Window. In fact, if you set the trace level to High you can get details on every step in the process of the binding.

So to the above code, I make two changes

  • Add a namespace reference to System.Diagnostics
  • Set PresentationTraceSources.TraceLevel=High on the binding I want to inspect.

<Window x:Class="DebugBindings.Window1"... xmlns:trace="clr-namespace:System.Diagnostics;assembly=WindowsBase">

<StackPanel>

<TextBox Text="{Binding ElementName=slider, Path=Value, Mode=OneWay, trace:PresentationTraceSources.TraceLevel=High}" Height="30" Width="100" Margin="10"/>

<Slider Minimum="0" Maximum="100" Value="20" Margin="10" x:Name="slider" />

StackPanel>

Window>

Now when I inspect the Output Window after running the application, I can see step-by-step details of the data binding process.

Created BindingExpression (hash=17654054) for Binding (hash=44624228)
Path: 'Value'
BindingExpression (hash=17654054): Default update trigger resolved to LostFocus
BindingExpression (hash=17654054): Attach to System.Windows.Controls.TextBox.Text (hash=52727599)
BindingExpression (hash=17654054): Resolving source
BindingExpression (hash=17654054): Found data context element: (OK)
Lookup name slider: queried TextBox (hash=52727599)
BindingExpression (hash=17654054): Resolve source deferred

BindingExpression (hash=17654054): Resolving source
BindingExpression (hash=17654054): Found data context element: (OK)
Lookup name slider: queried TextBox (hash=52727599)
BindingExpression (hash=17654054): Activate with root item Slider (hash=54371668)
BindingExpression (hash=17654054): At level 0 - for Slider.Value found accessor DependencyProperty(Value)
BindingExpression (hash=17654054): Replace item at level 0 with Slider (hash=54371668), using accessor DependencyProperty(Value)
BindingExpression (hash=17654054): GetValue at level 0 from Slider (hash=54371668) using DependencyProperty(Value): '20'
BindingExpression (hash=17654054): TransferValue - got raw value '20'
BindingExpression (hash=17654054): TransferValue - implicit converter produced '20'
BindingExpression (hash=17654054): TransferValue - using final value '20'

If I now enter text in the TextBox, I can check the Output Window to confirm that the binding was indeed broken!

BindingExpression (hash=17654054): Deactivate
BindingExpression (hash=17654054): Replace item at level 0 with {NullDataItem}
BindingExpression (hash=17654054): Detach

The only down side is that you have to manually add this property to each binding that you want to inspect.

Friday, April 18, 2008

Differences between the WPF and Silverlight 2 model

What are the differences between the WPF and Silverlight 2 model? If you have worked with WPF before you started working with Silverlight (like me!), then this is no doubt a key question lingering in your mind. I understand that Microsoft is planning to publish such a list, and that would be great when it comes. But until that is published, below is a list of differences that I have picked so far. Remember this is a comparision between WPF and Silverlight 2 Beta 1. Some of the gaps between these two related technologies may be filled in future releases of Silverlight.

The observations below are what apply to Silverlight 2 Beta 1.

Styles
  • Once you apply a style to a FrameworkElement, you cannot reassign a new style. This is bad news because this means that the user cannot pick a theme. Having said that, you can still reassign properties that have been once assigned. This means that you can reassign the control template since it is a property as well.
  • Styles cannot inherit from other styles - the 'BasedOn' property cannot be used.
  • Styles have to be referenced by a key. This means that you cannot drop a style for a button in your 'application.resources' hoping that all buttons in the application will pick up the style. You need to explicitly reference it by its key in all buttons in the application. Sigh!

Triggers

See my earlier post on this. There are no triggers in Silverlight Beta 1 for styles, control templates and data templates. Sigh, sigh and more sigh!

Say you are changing the control template of a button. When doing that, as part of the template you would want to define an animation that should fire when the mouse is over it. In WPF, you would just add a trigger in the control template that looks for the IsMouseOver property - which is a neat way of doing things. But in Silverlight, the developer who creates the control has to create event handlers for the MouseEnter and MouseLeave events, and in these event handlers he has to load storyboards with well known names. Then hope that the designer/developer skinning the control will supply storyboards with the same names!

Control Templates

Keeping aside the limitation control templates have that I explained above (in the triggers section), I think this is one area that Silverlight is better than WPF. Silverlight follows the parts model. This means that any control (controls that ship with Silverlight and custom controls) publish a well defined control contract. This control contract will define

  1. the minimum UIElements (and their names) that should be present in a control template for that control
  2. the storyboards (and their names) that should be present.

So this means that a designer/developer who is going to skin (or define a new control template for) the control needs to only look at the control contract to understand what the control expects to function properly.

In WPF, you have to search for the "PART_" prefix in the default control template. There is no well-defined control contract. I understand from the MIX talks that this is one area that WPF, the big brother, will listen to Silverlight and emulate it in future WPF releases.

Also, a custom control in Silverlight cannot inherit from UIElement or FrameworkElement classes though these classes are present (by the way, there is no Visual class in the class hierarchy in Silverlight). Custom controls should extend the Control class, or other classes like TextBox or Button that extend the Control class.

What makes skinning a control (read changing its control template) really complicated now is that at the moment Blend does not support templating. I'm sure that is coming. But until then, your XAML editing skills will be put to the test!

Resources

Dynamic resource references are not available. All are static references.

Data Binding

The following apply to Silverlight 2 Beta 1:

  • No binding the property of a UI control to the property of another UI control. There is no 'ElementName' property in the binding syntax.
  • No 'RelativeSource'
  • No 'OneWayToSource' - who needed it anyway?
  • No UpdateSourceTrigger property. All updates to the source (for two way binding) happen immediately, except in the case of TextBox in which case changes are propogated to the source when the focus is lost.
  • Cannot bind directly to XML data. Need to convert the XML to CLR objects, and then bind to the CLR object.
  • No ReadOnlyObservableCollection. Fortunately, the ObservableCollection is available which is more important.
  • No CollectionView for sorting and filtering.
  • No validation rules.
  • No DataTemplateSelector for dynamically selecting data templates based on data.
  • No XMLDataProvider and ObjectDataProvider.

Commanding

  • Commands and input bindings are not available in Silverlight 2 Beta 1.

These are a few things I observed about Silverlight 2. I plan to keep this list updated so that this will be a ready reference for someone looking for the differences between the WPF and Silverlight 2 model.