![](http://i.msdn.microsoft.com/Hash/030c41d9079671d09a62d8e2c1db6973.gif)
In order for changes to the source object to propagate to the target, the source must implement the INotifyPropertyChanged interface. INotifyPropertyChanged has the PropertyChanged event, which tells the binding engine that the source has changed so that the binding engine can update the target value.
In the following example, the MyColors class implements the INotifyPropertyChanged interface for OneWay binding.
public class MyColors : INotifyPropertyChanged
{
private SolidColorBrush _Brush1;
// Declare the PropertyChanged event.
public event PropertyChangedEventHandler PropertyChanged;
// Create the property that will be the source of the binding.
public SolidColorBrush Brush1
{
get { return _Brush1; }
set
{
_Brush1 = value;
// Call NotifyPropertyChanged when the source property
// is updated.
NotifyPropertyChanged("Brush1");
}
}
// NotifyPropertyChanged will raise the PropertyChanged event,
// passing the source property that is being updated.
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
}
}
}
To get change notification for collections bound to an ItemsControl, implement INotifyCollectionChanged in addition to INotifyPropertyChanged. If you implement INotifyCollectionChanged, changes to the collection, such as adding or removing an object, will propagate to the target. To get property change notification for objects in the collection, the objects must implement INotifyPropertyChanged.
Before implementing your own collection, consider using the ObservableCollection(Of T) class, which has a built-in implementation of INotifyCollectionChanged and INotifyPropertyChanged.
In TwoWay bindings, changes to the target automatically update the source, except when binding to the Text property of a TextBox. In this case, the update occurs when the TextBox loses focus.
You can disable automatic source updates and update the source at times of your choosing. For example, you can do this to validate user input from multiple controls before you update the bound data sources.
To disable automatic source updates, set the UpdateSourceTrigger property to Explicit. This setting affects all bindings that use the same Binding object (for example, when using an inherited data context). You must update the source for each binding individually, however. To update a binding, first call the FrameworkElement.GetBindingExpression method of a target element, passing in the target DependencyProperty. You can then use the return value to call the BindingExpression.UpdateSource method. The following example code demonstrates this process.
A binding source object can be treated either as a single object whose properties contain data or as a collection of objects. For example, you might want to display a list of items, such as monthly credit card bills. To do this, use an ItemsControl and use a DataTemplate to display each item in a collection. For more information on data templates, see How to: Customize Data Display with Data Templates.
<Grid.Resources>
<DataTemplate x:Name="dataTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Text="{Binding Month, Converter={StaticResource Converter1}}"/>
<TextBlock Grid.Column="1" Text="{Binding Total}"/>
</Grid>
</DataTemplate>
</Grid.Resources>
<ItemsControl x:Name="IC1" ItemsSource="{Binding}"
ItemTemplate="{StaticResource dataTemplate}"/>
You can enumerate over any collection that implements IEnumerable. If you want the target to update the ItemsSource when the collection changes, implement INotifyCollectionChanged. For more information on change notification, see the Change Notification section earlier in this topic.
You can also bind to instances of the CollectionViewSource class, which provides sorting, grouping, filtering, and currency support for other data sources. The CollectionViewSource enables you to display multiple views of data that stay synchronized with user selection changes.
You can also use CollectionViewSource to bind multiple controls to hierarchically-related data. For more information, see How to: Bind to Hierarchical Data and Create a Master/Details View.
The PagedCollectionView class provides another way to apply sorting, grouping, and filtering to another data source. This class also includes paging and editing, and provides a data source for controls such as DataPager.
For information about encapsulating a generic list in an object so that you can bind a control to it, see the first code examples for List(Of T) and Dictionary(Of TKey, TValue).
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Windows.Navigation;
using System.ComponentModel;
using System.Collections.ObjectModel;
namespace PhoneApp5
{
public partial class MainPage : PhoneApplicationPage, INotifyPropertyChanged
{
// Constructor
public MainPage()
{
InitializeComponent();
}
public ObservableCollection<DirectorySource> dataSource;
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
UpdateUI();
}
private void UpdateUI()
{
if (directoryListBox.ItemsSource == null)
{
if (dataSource == null)
{
dataSource = GetDataSource();
}
directoryListBox.ItemsSource = dataSource;
}
}
private ObservableCollection<DirectorySource> GetDataSource()
{
ObservableCollection<DirectorySource> dataSource;
int i = 0;
switch (i)
{
case 1: dataSource = GetDataSourceOne();
break;
case 2: dataSource = GetDataSourceTwo();
break;
case 3: dataSource = GetDataSourceThreee();
break;
default: dataSource = GetAllDataSource();
break;
}
return dataSource;
}
private ObservableCollection<DirectorySource> GetDataSourceOne()
{
throw new NotImplementedException();
}
private ObservableCollection<DirectorySource> GetDataSourceTwo()
{
throw new NotImplementedException();
}
private ObservableCollection<DirectorySource> GetDataSourceThreee()
{
throw new NotImplementedException();
}
private ObservableCollection<DirectorySource> GetAllDataSource()
{
for (int i = 1; i < 10; i++)
{
DirectorySource directorySource = new DirectorySource();
directorySource.DisplayMemo = i.ToString();
directorySource.DisplayName = i.ToString();
DataManager.source.Add(directorySource);
}
SortSource();
return DataManager.source;
}
private void SortSource()
{
List<DirectorySource> test = DataManager.source.ToList<DirectorySource>();
test.Sort();
DataManager.source = new ObservableCollection<DirectorySource>(test);
dataSource = DataManager.source;
}
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
base.OnNavigatingFrom(e);
}
private void button1_Click(object sender, RoutedEventArgs e)
{
Random rnd1 = new Random(0);
DirectorySource directorySource = new DirectorySource();
// directorySource.DisplayMemo = rnd1.Next().ToString();
//directorySource.DisplayName = rnd1.Next().ToString();
directorySource.DisplayMemo = "0";
directorySource.DisplayName = "0";
DataManager.source.Add(directorySource);
SortSource();
}
private void ReSetDataSource()
{
directoryListBox.ItemsSource = dataSource;
}
private void button2_Click(object sender, RoutedEventArgs e)
{
DataManager.source[1].DisplayMemo = "200";
DataManager.source[1].DisplayName = "200";
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
}
x:Class="PhoneApp5.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True">
<!--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="page name" 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,291">
<Grid.RowDefinitions>
<RowDefinition>
<RowDefinition.Height>100</RowDefinition.Height>
</RowDefinition>
<RowDefinition>
<RowDefinition.Height>100</RowDefinition.Height>
</RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1"/>
<ColumnDefinition Width="169" />
<ColumnDefinition Width="190" />
<ColumnDefinition Width="96*" />
</Grid.ColumnDefinitions>
</Grid>-->
<ListBox BorderThickness="0" Grid.Row="1" Name="directoryListBox"
SelectionMode="Single" Margin="0,0,0,164">
<ListBox.ItemTemplate >
<DataTemplate >
<Grid Margin="12,0,0,5" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="45"></RowDefinition>
<!--<RowDefinition Height="25"></RowDefinition>-->
</Grid.RowDefinitions>
<!--<Image Name="photoImage" Source="{Binding Path=Image}" Width="70" Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Stretch="UniformToFill" />-->
<TextBlock Text="{Binding Path=DisplayName}" Name="name"
Grid.Row="0" Grid.Column="0"
VerticalAlignment="Top" HorizontalAlignment="Left"
Style="{StaticResource PhoneTextLargeStyle}"></TextBlock>
<TextBlock Name="titleDept" Text="{Binding Path=DisplayMemo}"
Grid.Row="0" Grid.Column="1"
VerticalAlignment="Center" HorizontalAlignment="Left"
Style="{StaticResource PhoneTextSubtleStyle}" >
</TextBlock>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Content="Add" Grid.Row="1" Height="72" HorizontalAlignment="Left" Margin="32,465,0,0" Name="button1" VerticalAlignment="Top" Width="110" Click="button1_Click" />
<Button Content="Change" Grid.Row="1" Height="72" HorizontalAlignment="Left" Margin="148,465,0,0" Name="button2" VerticalAlignment="Top" Width="130" Click="button2_Click" />
</Grid>
<!--Sample code showing usage of ApplicationBar-->
<!--<phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
<shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.png" Text="Button 1"/>
<shell:ApplicationBarIconButton IconUri="/Images/appbar_button2.png" Text="Button 2"/>
<shell:ApplicationBar.MenuItems>
<shell:ApplicationBarMenuItem Text="MenuItem 1"/>
<shell:ApplicationBarMenuItem Text="MenuItem 2"/>
</shell:ApplicationBar.MenuItems>
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>-->
</phone:PhoneApplicationPage>
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace PhoneApp5
{
public static class DataManager
{
public static ObservableCollection<DirectorySource> source = new ObservableCollection<DirectorySource>();
}
public class DirectorySource : INotifyPropertyChanged, IComparable
{
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
private string displayName = string.Empty;
private string displayMemo = string.Empty;
public DirectorySource()
{
}
public string DisplayName
{
get
{
return this.displayName;
}
set
{
if (this.displayName != value)
{
this.displayName = value;
OnPropertyChanged("DisplayName");
}
}
}
public string DisplayMemo
{
get
{
return this.displayMemo;
}
set
{
if (this.displayMemo != value)
{
this.displayMemo = value;
OnPropertyChanged("DisplayMemo");
}
}
}
protected void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
#region IComparable Members
public int CompareTo(object obj)
{
DirectorySource test = obj as DirectorySource;
return string.Compare(this.DisplayName, test.DisplayName);
}
#endregion
}
}