Blogger Tricks

19 Jun 2012

Two-way data binding in Windows 8

Two-way data binding in Windows 8 Last week we looked at the INotifyPropertyChanged and INotifyCollectionChanged interfaces and the ObservableCollection object, which are important parts of data binding in the XAML model. This week we will find out how two-way data binding works. Two-way data binding will allow your UI to make changes to the data without having to know the specifics of the data.
I started by creating a simple object to hold my data (an integer and a string property). There is nothing fancy here, just two properties. This object was a bit more complex than you might think; I added a third read-only property that constructed its value from the other two properties to neatly format them into output. I also implemented INotifyPropertyChanged. I fired off a PropertyChangedEventHandler for the int and string properties when their set accessor was called. In addition, I fired the event for the formatted value property each time either of the other two were called. The code is in Code sample A.

Code sample A
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DataBindingDemo
{
class SimpleBoundData : INotifyPropertyChanged
{
private int _intValue;
public int IntValue {
get
{
return _intValue;
}
set
{
_intValue = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("IntValue"));
PropertyChanged(this, new PropertyChangedEventArgs("Values"));
}
}
}
private string _stringValue;
public string StringValue {
get
{
return _stringValue;
}
set
{
_stringValue = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("StringValue"));
PropertyChanged(this, new PropertyChangedEventArgs("Values"));
}
}
}
public string Values
{
get
{
return "IntValue: " + IntValue.ToString() + "\nStringValue: " + StringValue;
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
Next, I built the solution to make the classes visible to the data source creation tool. I selected the Grid that defines the main window in my XAML, and in the properties toolbar, I created a new Data Context, pointing it at my simple data class. This also let me set default values if I wanted to, though that gave me problems when I tried it (I am using the Visual Studio 2012 beta on the Windows 8 Release Preview, so that may be the problem).
On the UI side of things, I made a TextBox and a Slider control. On each one, I selected the “Value” property, and there is a little box you can click to create a new data binding. They are aware of the context that the parent Grid has, and the tool offered me the properties from the simple data class. I hooked the string property to the TextBox and the int property to the Slider. I went into the additional settings to ensure that both were set to be “Two Way” bindings. Then I made a TextBlock and bound it to the formatted text property. The XAML is in Code sample B.
Code sample B
<Page
x:Class="DataBindingDemo.MainPage"
IsTabStop="false"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:DataBindingDemo"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Grid.DataContext>
<local:SimpleBoundData x:Name="simpleDataContext"/>
</Grid.DataContext>
<TextBox x:Name="stringValueEdit" HorizontalAlignment="Left" Margin="41,75,0,0" TextWrapping="Wrap" Text="{Binding StringValue, Mode=TwoWay}" VerticalAlignment="Top" Width="348"/>
<Slider x:Name="intValueEdit" HorizontalAlignment="Left" Margin="41,169,0,0" VerticalAlignment="Top" Width="348" Value="{Binding IntValue, Mode=TwoWay}"/>
<TextBlock x:Name="results" HorizontalAlignment="Left" Margin="322,281,0,0" TextWrapping="Wrap" Text="{Binding Values, Mode=OneWay}" VerticalAlignment="Top" Height="48" Width="195"/>
</Grid>
</Page>
Now for the fun part! Hit the Run button and try editing the text or moving the slider around, and you will see the TextBlock bound to the formatted text shows us exactly what we hope to see… that changing the data in the controls has an immediate effect on their underlying data, and that our PropertyChangeEventHandler is being dealt with properly (Figure C).
Figure C
Yes, that’s Windows 8 in a VM on a Mac. (Click the image to enlarge.)
From here, we could do all sorts of things. The obvious next step would be to alter the get/set accessors so they interact with a true data source (a database, XML file, Web service, etc.), but that is up to you to handle.
By Justin James