DataBinding is a mechanism in WPF applications that provides a simple and easy way for applications to display and interact with the data. It allows the flow of data between UI and business model. Any modification done on data in your business model after binding is done, will automatically reflect to the UI, and vice versa.
Binding can be one directional or bidirectional. The source of databinding can be a normal .NET property or Dependency property, however the target property must be a Dependency property.
For making binding work properly, both sides of the property must provide change in notification which will tell the binding to update the target value. In normal .NET properties, it can be achieved by using INotifyPorpertyChanged interface. And for Dependency properties, it is done by PropertyChanged callback of property metadata.
Databinding is achieved in XAML by using Binding mark-up extension i.e. {Binding}.
Eaxmple
- <Window.Resources>
- <local:Employee x:Key="MyEmployee" EmployeeNumber="123" FirstName="John" LastName="Doe" Department="Product Development" Title="QA Manager" /> </Window.Resources>
- <Grid DataContext="{StaticResource MyEmployee}">
- <TextBox Text="{Binding Path=EmployeeNumber}"></TextBox>
- <TextBox Text="{Binding Path=FirstName}"></TextBox>
- <TextBox Text="{Binding Path=LastName}" />
- <TextBox Text="{Binding Path=Title}"></TextBox>
- <TextBox Text="{Binding Path=Department}" />
- </Grid>
DataContext
Datacontext property is used for setting the data to UI. If you do not explicitly define source of binding, then it takes data context as default.
Types of Binding
- OneWay
- TwoWay
- OneWayToSource
- OneTime
One Way
In this type of binding, data is bound to its source i.e. business model to its target i.e. UI.
In xaml file
- <Window x:Class="WPFDataBinding.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WPFDataBinding" mc:Ignorable="d" Title="MainWindow" Height="350" Width="604">
- <Grid>
- <Grid.RowDefinitions>
- <RowDefinition Height="Auto" />
- <RowDefinition Height="Auto" />
- <RowDefinition Height="*" /> </Grid.RowDefinitions>
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="Auto" />
- <ColumnDefinition Width="200" /> </Grid.ColumnDefinitions>
- <Label Name="nameLabel" Margin="2">_Name:</Label>
- <TextBox Name="nameText" Grid.Column="1" Margin="2" Text="{Binding Name, Mode = OneWay}" />
- <Label Name="ageLabel" Margin="2" Grid.Row="1">_Age:</Label>
- <TextBox Name="ageText" Grid.Column="1" Grid.Row="1" Margin="2" Text="{Binding Age, Mode = OneWay}" />
- <StackPanel Grid.Row="2" Grid.ColumnSpan="2">
- <Button Content="_Show..." Click="Button_Click" /> </StackPanel>
- </Grid>
- </Window>
Now, in xaml.cs file,
- using System.Windows;
- namespace WPFDataBinding {
- public partial class MainWindow: Window {
- Person person = new Person {
- Name = "Salman", Age = 26
- };
- public MainWindow() {
- InitializeComponent();
- this.DataContext = person;
- }
- private void Button_Click(object sender, RoutedEventArgs e) {
- string message = person.Name + " is " + person.Age;
- MessageBox.Show(message);
- }
- }
- public class Person {
- private string nameValue;
- public string Name {
- get {
- return nameValue;
- }
- set {
- nameValue = value;
- }
- }
- private double ageValue;
- public double Age {
- get {
- return ageValue;
- }
- set {
- if (value != ageValue) {
- ageValue = value;
- }
- }
- }
- }
- }
Two Way
In this, data is getting updated from both sides i.e. source and target. If there is any change from UI, it updates the business model, and vice versa.
- <Window x:Class="WPFDataBinding.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WPFDataBinding" mc:Ignorable="d" Title="MainWindow" Height="350" Width="604">
- <Grid>
- <Grid.RowDefinitions>
- <RowDefinition Height="Auto" />
- <RowDefinition Height="Auto" />
- <RowDefinition Height="*" /> </Grid.RowDefinitions>
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="Auto" />
- <ColumnDefinition Width="200" /> </Grid.ColumnDefinitions>
- <Label Name="nameLabel" Margin="2">_Name:</Label>
- <TextBox Name="nameText" Grid.Column="1" Margin="2" Text="{Binding Name, Mode = TwoWay}" />
- <Label Name="ageLabel" Margin="2" Grid.Row="1">_Age:</Label>
- <TextBox Name="ageText" Grid.Column="1" Grid.Row="1" Margin="2" Text="{Binding Age, Mode = TwoWay}" />
- <StackPanel Grid.Row="2" Grid.ColumnSpan="2">
- <Button Content="_Show..." Click="Button_Click" /> </StackPanel>
- </Grid>
- </Window>
OneWayToSource
OneWayToSource is the reverse of OneWay binding; it updates the source property when the target property changes.
OneTime
This has the same behaviour as OneWay except it will only update the user interface one time. This should be your default choice for binding.