×
Namespaces

Variants
Actions
Revision as of 02:06, 12 September 2012 by hamishwillee (Talk | contribs)

Data Binding to controls on Windows Phone

From Nokia Developer Wiki
Jump to: navigation, search

This article explains how bind data objects in code to objects declared in your Windows Phone app's XAML UI.

See Also
WP Metro Icon File.png
WP Metro Icon UI.png
SignpostIcon XAML 40.png
WP Metro Icon WP8.png
SignpostIcon WP7 70px.png
Article Metadata
Code ExampleTested with
SDK: Windows Phone 7.1
Devices(s): Lumia 800,710
Compatibility
Platform(s): Windows Phone 7.5 (mango)
Windows Phone 8
Windows Phone 7.5
Article
Keywords: INotifyPropertyChanged
Created: gaba88 (09 Sep 2012)
Last edited: hamishwillee (12 Sep 2012)

Contents

Introduction

Windows Phone apps typically define their UI declaratively using XAML (in Expression Blend). While some UI component values may be hardcoded in XAML, many will be provided by data sources (objects, databases, XML feeds). Data binding is the technique which provides the connection between the XAML components and their values as defined in code.

This code example shows how define controls in XAML and bind their data values to an object defined in the C# file. It also shows how to use the INotifyPropertyChanged interface class to ensure that the UI is updated whenever the underlying code changes.

The associated example creates three text boxes in XAML, and uses binding to update their values with information from C# objects.

Figure 1: Data Binding in Windows Phone

Creating the XAML UI

First we create a simple Windows Phone page which contains a title panel followed by a content panel (Grid) containing three TextBox - which will display manufacturer, software and model text. Note that the content Grid is named ContentPanel, and we will later use this name to bind to the XAML from the C# code (and similarly the Names of each of the TextBoxes).

<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
 
<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="DataBindingExample" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
 
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<TextBox Height="70" HorizontalAlignment="Left" Margin="0,130,0,0" Name="manufacturerBox" Text="manufacturer" VerticalAlignment="Top" Width="450" />
<TextBox Height="72" HorizontalAlignment="Left" Margin="0,206,0,0" Name="modelBox" Text="model" VerticalAlignment="Top" Width="450" />
<TextBox Height="72" HorizontalAlignment="Left" Margin="6,284,0,0" Name="softwareBox" Text="software" VerticalAlignment="Top" Width="450" />
</Grid>
</Grid>

The above XAML code contains hard-coded Text property values for the manufacturer, model and software. To bind the controls to data we first need to update the required properties with the {Binding} keyword. The keyword allows us to specify the name of the property we want to bind to, and whether the binding is two way (ie whether changes to the UI will propagate to the underlying object). Both of these two properties are optional: if you just specify {Binding} then the bound object's ToString() method will be called to get the property value and the binding is one way.

In this example we implement one way binding and specify the particular properties of the bound object to use for the Text (ie the manufacturer property of the bound object will be used for the text value of the manufacturerBox property.

The updated XAML code looks like:

 <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<TextBox Height="70" HorizontalAlignment="Left" Margin="0,130,0,0" Name="manufacturerBox" Text="{Binding manufacturer}" VerticalAlignment="Top" Width="450" />
<TextBox Height="72" HorizontalAlignment="Left" Margin="0,206,0,0" Name="modelBox" Text="{Binding model}" VerticalAlignment="Top" Width="450" />
<TextBox Height="72" HorizontalAlignment="Left" Margin="6,284,0,0" Name="softwareBox" Text="{Binding software}" VerticalAlignment="Top" Width="450" />
</Grid>

At this point we still haven't defined the data source (though we know from the XAML it has properties manufacturer, model and software) and bound it to the XAML. This is done in the C# code, which we define in the following sections.


Create and bind the data source

Next we create PhoneModel.cs, and define our PhoneModel class. Note how the class has C# properties that match the bound properties in our XAML.

namespace DataBindingEx
{
public class PhoneModel
{
public string manufacturer { get; set; }
public string model { get; set; }
public string software { get; set; }
 
}
}

The next step is to create an instance of the PhoneModel and bind it to the XAML, which we do using the DataContext property. The best place to perform the binding is when page initialisation completes, in the MainPage_Loaded() event handler as shown below.

namespace DataBindingEx
{
public partial class MainPage : PhoneApplicationPage
{
// declare PhoneModel object
PhoneModel _phnModel;
 
// Constructor
public MainPage()
{
InitializeComponent();
 
// add page load event handler
Loaded += MainPage_Loaded;
}
 
void MainPage_Loaded(object sender,RoutedEventArgs e)
{
// initialize _phnModel object
_phnModel = new PhoneModel
{
manufacturer = "Nokia",
model = "Lumia 920",
software = "windows phone 8"
};
 
// call utility method to set DataContext
setDataContext();
}
 
private void setDataContext()
{
ContentPanel.DataContext = _phnModel;
}
}
}

The interesting part of the code is the setDataContext() method:

private void setDataContext()
{
ContentPanel.DataContext = _phnModel;
}

The ContentPanel is a reference to the Grid object defined in XAML (Grid x:Name="ContentPanel"). We bind to this by assigning our PhoneModel instance to the referenced object's DataContext. Now when the page is loaded the the properties will be taken from our PhoneModel instance when the page is loaded. This results in the screen shown in #Figure1.

At this point the binding is one-off (the properties are updated in the UI only on page load) and one-way (changes to the UI do not affect the C# object values). The following sections explain how you can make the UI responsive to code changes.


Updating the UI when the properties change in code

Now one can simply say if we change the properties of PhoneModel class via some events then that should also update the UI, but sadly that's not the case. When we are binding properties to attributes simply changing the value of the properties will not update the UI, to update the UI we need to use the simple INotifyPropertyChanged interface. We need to implement INotifyPropertyChanged and raise an event to update the property.

So first we need to change the PhoneModel class to implement INotifyPropertyChanged Interface. Now PhoneModel.cs will look like:

using System.ComponentModel;
using System.Windows.Data;
 
namespace DataBindingEx
{
public class PhoneModel:INotifyPropertyChanged
{
private string _manufacturer;
private string _model;
private string _software;
 
 
public string manufacturer
{
get { return _manufacturer; }
 
set
{
_manufacturer = value;
NotifyPropertyChanged("manufacturer");
}
}
public string model
{
get { return _model; }
 
set
{
_model = value;
NotifyPropertyChanged("model");
}
}
public string software
{
get { return _software;}
set
{
_software = value;
NotifyPropertyChanged("software");
}
}
 
public event PropertyChangedEventHandler PropertyChanged;
 
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
 
}
}

The above code snippet make PhoneModel class to implement INotifyPropertyChanged, and makes a utility method name NotifyPropertyChanged, that method raises the PropertyChanged event with the name of the property which needs to be updated at the UI. All properties needs to call this NotifyPropertyChanged utility method.

To update the properties of the model and to see whether the UI get's updated or not we will add a button and on click event of the button we will change our properties and will see if the UI get updates or not, so the code for MainPage.xaml.cs goes like:

namespace DataBindingEx
{
public partial class MainPage : PhoneApplicationPage
{
PhoneModel _phnModel;
 
// Constructor
public MainPage()
{
InitializeComponent();
Loaded += MainPage_Loaded;
}
 
void MainPage_Loaded(object sender,RoutedEventArgs e)
{
 
_phnModel = new PhoneModel
{
manufacturer = "Nokia",
model = "Lumia 920",
software = "windows phone 8"
};
 
 
setDataContext();
}
 
private void setDataContext()
{
ContentPanel.DataContext = _phnModel;
}
 
// utility method which changes the PhoneModel properties
private void setPhoneProperties(String manufacturer, String model, String software)
{
_phnModel.manufacturer = manufacturer;
_phnModel.model = model;
_phnModel.software = software;
 
}
 
// called when update button is clicked
private void updateBtn_Click(object sender, RoutedEventArgs e)
{
setPhoneProperties("Nokia", "Lumia 900", "windows Phone 7.8");
}
}
}

and when you click the button the screen should look like:

Data Binding in Windows Phone


Summary

Property Binding is one of the best and simplest ways to glue your data with UI attributes.

References

829 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×