Monday 13 May 2013

Data Binding XAML control to property in code behind

Sample code this article

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");
}
}
}

2 comments:

  1. How to post code same as asp.net code in blog. please tell me how can i do it ?
    I have blog but how to post same color code of asp.net in our blog. I copy code then paste in word and then published code but it have black color code show.

    ReplyDelete
  2. Sorry but none of your examples work. Why do you post code that does not work?

    ReplyDelete