One reason I’ve been so quiet over the past couple months, is I have been scrambling to update Chad Campbell and John Stockton’s excellent Manning Silverlight 2 in Action book to Silverlight 3, under the title Silverlight in Action 2nd Edition (the Amazon info is out of date), to be released this fall.
I’ve done a little restructuring (but not a ton) in the process, and have also been covering as many new Silverlight 3 goodies as I can, as well as a couple extras like ViewModel and .NET RIA Services.
I just finished writing the section about UI Element binding in Silverlight 3, and thought I’d share some of the pre-edited version with you all, since the example here solves something I’m often asked to do in Silverlight applications. Enjoy!
As a reminder, Manning Early Access Program (MEAP) members will be getting chapters of the book in the next couple days, with a much larger release of content just after Silverlight 3 goes live. If you’re looking to get an edge up on Silverlight 3, I’d definitely recommend joining MEAP.
7.2.3 Binding to a UI element
Binding one or more properties of a UI Element to values on an entity, ViewModel or business object is certainly a compelling use of binding. Sometimes, though, you want to use binding for things we wouldn't traditionally consider "data", things within the user interface. You may want to bind the height of two controls together so that they resize equally, or perhaps you want to bind three sliders to the x, y, and z-axis rotations respectively of a plane (see chapter n for more information on 3d rotation in Silverlight). Rather than binding to gather input or display data to the user, you're binding to avoid writing extra plumbing code.
Let's say that you want to display a count of characters entered into a TextBox in real-time. Something like the figure below.
You could certainly do that in code, but that would be fairly uninteresting code to write, and would need to refer to XAML elements by name, or have event handlers wired in XAML, introducing a dependency on the specific page's code-behind and making it less portable and potentially more brittle. In addition, you'd find yourself doing it enough that you'd either wrap the TextBox in your own CountingCharsTextBox control, or add a helper buddy class or something.
Or, if you prefer a XAML approach, which I hope I've sold you on by now, Silverlight 3 introduced the concept of Element Binding. Element Binding allows you to bind the properties of one FrameworkElement to another FrameworkElement. The usual restrictions apply (target must be a DependencyProperty, source must notify of changes) so you cannot using element binding quite everywhere.
To produce the above TextBox with the automatic count of characters using Element Binding, the markup is pretty straight-forward and entirely self-contained:
<StackPanel Orientation="Vertical" Margin="50">
<TextBlock Text="Tweet (max 140 characters)" />
<TextBox x:Name="tweetText"
MaxLength="140"
Text="Right now I'm writing a book" />
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Text.Length, ElementName=tweetText}" />
<TextBlock Text="/" />
<TextBlock Text="{Binding MaxLength, ElementName=tweetText}" />
</StackPanel>
</StackPanel>
The above XAML will show a TextBox with a count of characters underneath it. The character count will update in real-time to show the number of characters typed into the TextBox. Note also that the MaxLength displayed under the textbox is actually coming from the TextBox itself (the 140 in the label is not, however). The key item that makes this happen is the ElementName parameter in the binding expression. ElementName is, as it suggests, the name of another element on the XAML page.