Binding to property defined in code behind
using System.Windows;
namespace WPFDataBindingCodeBehind
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private string _helloText = "Hello World";
public string HelloText
{
get { return _helloText; }
set { _helloText = value; }
}
public MainWindow()
{
InitializeComponent();
}
}
}
One important point to note in code behind above is that _helloText string has been assigned value at the time of Declaration. Hence when controls are loaded and binding happens, this value is already available and displayed. Below we would see what happens when we change value in Window Load event and how to handle that.
1. Binding using RelativeResource
<TextBlock Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}, Path=HelloText}"></TextBlock>
2. Binding using ElementName
Here we are using Element to Element Binding syntax. Name of Window is set to “myWindow”. Then Text property binds to “HelloText” property in element “myWindow”.
<Window x:Class="WPFDataBindingCodeBehind.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="myWindow"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<TextBlock Text="{Binding ElementName=myWindow, Path=HelloText}"></TextBlock>
</StackPanel>
</Window>
3. Binding using DataContext of Window set to Self
Here DataContext of entire window is set to code behind. All controls in this window would inherit this DataContext and hence their source for data binding would become code behind. So all controls can directly bind to properties.
<Window x:Class="WPFDataBindingCodeBehind.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}">
<StackPanel>
<TextBlock Text="{Binding Path=HelloText}"></TextBlock>
</StackPanel>
</Window>
4. Binding using DataContext of Parent element set to Window
Instead of setting DataContext of entire window to code behind, this syntax would set DataContext of parent StackPanel to code behind. Syntax for setting DataContext is similar to syntax is method 1.
<Window x:Class="WPFDataBindingCodeBehind.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}">
<TextBlock Text="{Binding Path=HelloText}"></TextBlock>
</StackPanel>
</Window>
Important Note
Now, If we change the value in Window Load event then this changes would not be reflected. TextBlock will still display “Hello World” string. This is because when controls are loaded in InitializeComponent(), binding happens for first time and value is set to “Hello World”.
<Window x:Class="WPFDataBindingCodeBehind.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
using System.Windows;
using System.ComponentModel;
namespace WPFDataBindingCodeBehind
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private string _helloText = "Hello World";
public string HelloText
{
get { return _helloText; }
set { _helloText = value; }
}
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
HelloText = "Value Changed";
}
}
}
Implementing INotifyPropertyChanged
Once binding happens, any changes to the source value needs to be notified to the target control so that control can update the binding value. To achieve this, WPF provides INotifyPropertyChanged mechanism.
using System.Windows;
using System.ComponentModel;
namespace WPFDataBindingCodeBehind
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
private string _helloText = "Hello World";
public string HelloText
{
get { return _helloText; }
set { _helloText = value; }
}
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
HelloText = "Value Changed";
RaisePropertyChanged("HelloText");
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Binding Collections
Collection can be bound same way as property above. We have declared an ObservableCollection<string> named “myString” and instantiated at the time of declaration. This string is then bound to ListBox. ObservableCollection is a specialized type of List which provides built-in implementation of INotifyPropertyChanged and hence when any items are added/removed from the collection, same is notified to the target control.
XAML
<Window x:Class="WPFDataBindingCodeBehind.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="myWindow"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
<StackPanel>
<ListBox ItemsSource="{Binding ElementName=myWindow, Path=MyStrings}"></ListBox>
</StackPanel>
</Window>
Code Behind
using System.Windows;
using System.ComponentModel;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace WPFDataBindingCodeBehind
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private ObservableCollection<string> myStrings = new ObservableCollection<string>();
public ObservableCollection<string> MyStrings
{
get { return myStrings; }
set { myStrings = value; }
}
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
MyStrings.Add("Apple");
MyStrings.Add("Oranges");
MyStrings.Add("Mango");
MyStrings.Add("Banana");
MyStrings.Add("Watermelon");
}
}
}