WPF has built-in support for binding UI elements. For example, when the user changes the position of the slider the width of the button changes, all done through binding in XAML. Unfortunately, Silverlight does not have this built-in support. So what can be done?
Using an intermediary class and generics it is fairly simple to roll your own. Let's take a look at how it works.
Using VS2008 create a Silverlight application. I called the project BindingBetweenUIControls, rename the TestPage's to default and am using VB.NET. Next, in the Silverlight project, add a class called IntermediaryUIBinding.vb. Figure 1 shows the solution explorer.
Figure 1: Solution Explorer
Edit the class InterediaryUIBinding.vb. Listing 1 shows the complete listing of this class.
Listing 1: The class IntermediaryUIBinding used to bind UI controls.
1 Imports System.ComponentModel
2
3 'Intermediary class used to binding to UI properties of type double.
4 Public Class IntermediaryUIBinding(Of T)
5 Implements INotifyPropertyChanged
6
7 Public Event PropertyChanged( _
8 ByVal sender As Object, _
9 ByVal e As System.ComponentModel.PropertyChangedEventArgs) _
10 Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
11
12 Private _IntermediaryValue As T
13 Public Property IntermediaryValue() As T
14 Get
15 Return _IntermediaryValue
16 End Get
17 Set(ByVal value As T)
18 _IntermediaryValue = value
19 RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("IntermediaryValue"))
20 End Set
21 End Property
22
23 Public Sub New(ByVal value As T)
24 IntermediaryValue = value
25 End Sub
26
27 End Class
This generic class implements INotifyPropertyChanged which is a requirement if you want to provide two way data binding. Please refer to the previous post Silverlight Data Binding, using INotifyPropertyChanged and ObservableCollection. The generic implementation permits this class to be used for UI properties of various types. In this example we will be binding a double value. The actual class implementation is extremely simple containing a single property that raises the PropertyChanged event whenever the value is modified. This event is used by the binding infrastructure to notify the UI of data changes.
The UI for this Silverlight control is shown in listing 2.
Listing 2: Page.xaml with the UI data binding markup.
1 <UserControl x:Class="BindingBetweenUIControls.Page"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 >
5 <Grid x:Name="LayoutRoot" Background="Bisque" Width="400" Height="300">
6 <Grid.RowDefinitions>
7 <RowDefinition Height="150"/>
8 <RowDefinition/>
9 <RowDefinition/>
10 </Grid.RowDefinitions>
11 <TextBlock FontSize="18" TextWrapping="Wrap" Margin="10">
12 <Run>Using an intermediary object you can bind properties of controls.</Run>
13 <Run>Change the slider position and watch the button width change.</Run>
14 </TextBlock>
15 <Slider
16 x:Name="bindingSlider"
17 Value="{Binding IntermediaryValue, Mode=TwoWay}"
18 Width="300" Minimum="100" Maximum="300"
19 Grid.Row="1" />
20 <Button
21 x:Name="bindingButton"
22 Width="{Binding IntermediaryValue}" Height="50"
23 Content="Binding UI" Grid.Row="2" />
24 </Grid>
25 </UserControl>
The markup contains two controls; a slider and a button. The slider, line 17, has it's Value attribute bound to the IntermediaryValue property and uses two way data binding. Similarly , the button control, line 22, has it's Width attribute bound to the same IntermediaryValue property but does not use two way data binding. The two way binding for the slider is necessary since we want the underlying data stored in the property IntermediaryValue to change whenever the slider position is changed by the user.
Finally, all that needs to be done is to set the DataContext of a parent control. This is easily done in the code behind of Page.xaml and is shown in listing 3.
Listing 3: Page.xaml,vb Codebehind
1 Partial Public Class Page
2 Inherits UserControl
3
4 Public Sub New()
5 InitializeComponent()
6 End Sub
7
8 Private Sub Page_Loaded( _
9 ByVal sender As Object, _
10 ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
11 LayoutRoot.DataContext = New IntermediaryUIBinding(Of Double)(bindingSlider.Value)
12 End Sub
13
14 End Class
Fairly simple, line 11 sets the DataContext of the grid control to an instance of the Intermediary class specifying a generic type of Double. The constructor parameter specifies the initial value of the slider. Now when the users changes the position of the slider the binding infrastructure will update the underlying data store, i.e., the property IntermediaryValue and since this property is bound to the button's width it will change accordingly.
That's it binding between Silverlight UI controls.
This post was inspired by a presentation by Dan Borkowski at the Toronto Silverlight User Group.
If you would like to see this code in action or would like to download the code then visit my Silverlight Demo Gallery.
Guess the movie
Where do you think you're going? Nobody's leaving. Nobody's walking out on this fun, old-fashioned family Christmas. No, no. We're all in this together. This is a full-blown, four-alarm holiday emergency here. We're gonna press on, and we're gonna have the hap, hap, happiest Christmas since Bing Crosby tap-danced with Danny fucking Kaye. And when Santa squeezes his fat white ass down that chimney tonight, he's gonna find the jolliest bunch of assholes this side of the nuthouse.