Introduction to binding in WPF
Join the DZone community and get the full member experience.
Join For FreeFirst of all, as you can see from the term “binding”, something is going to be bound to something else. In WPF, various control properties can be bound to other properties (from other controls or user-specified).
Binding can be performed both from the XAML side of a WPF project, and from code-behind. In this article I will focus on the XAML representation.
There are two type of binding behaviors – one-way and two-way binding. One-way binding means that a property can influence another one, but not the other way around. Two-way binding means that both properties influence each other. To illustrate both examples, let’s take a look at this sample XAML, that shows one-way binding to a Text property:
<Window x:Class="WPF_Test.MainWindow"As you see here, the second TextBox control doesn’t have a direct Text property assignment, but rather a binding element - "{Binding ElementName=textBox1,Path=Text}" Binding elements are placed inside braces. For this specific example, I am binding the property of a control to another one, therefore I am using ElementName to point to the referenced element. Path shows the path to the property I am going to bind to, inside the referenced control. If you run the application, you will see that once you modify the text in the first TextBox control, the same text will appear in the second TextBox. This is a very simple representation of one-way binding.
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="300" Width="300"
Loaded="Window_Loaded">
<Grid>
<TextBox Height="35" HorizontalAlignment="Left" Margin="12,12,0,0" Name="textBox1" VerticalAlignment="Top" Width="150" />
<TextBox Height="35" HorizontalAlignment="Left" Margin="12,53,0,0" Name="textBox2" VerticalAlignment="Top" Width="150" Text="{Binding ElementName=textBox1,Path=Text}"/>
</Grid>
</Window>
Now let’s take a look at an example showing the capabilities of two-way binding.
<Window x:Class="WPF_Test.MainWindow"The XAML markup is quite similar, but now the binding element has changed a bit - "{Binding ElementName=textBox1,Path=Text,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}".
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="300" Width="300"
Loaded="Window_Loaded">
<Grid>
<TextBox Height="35" HorizontalAlignment="Left" Margin="12,12,0,0" Name="textBox2" VerticalAlignment="Top" Width="150" />
<TextBox Height="35" HorizontalAlignment="Left" Margin="12,53,0,0" Name="textBox1" VerticalAlignment="Top" Width="150" Text="{Binding ElementName=textBox2,Path=Text,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</Window>
I am binding to the same property, however, I am explicitly showing that this is a two-way binding via Mode. UpdateSourceTrigger indicates the cause of the source (in this case the first TexBox) property change and PropertyChanged means that the analogue property (same as I am binding to) is changed.
I am using this instead of another "{Binding ElementName=textBox1,Path=Text}" inside the second TextBox element, however this is also an acceptable solution.
Binding can be made to almost anything. Let’s experiment a bit with user-set properties. In the code-behind, I am going to create a property called ProgressValue:
double progress = 0;I am going to use it to bind to a ProgressBar control, that will later pass the value to the progress bar in the Taskbar (if you are using Windows 7 only). If you are not using Windows 7, you can familiarize yourself with the basic principles of external property binding, as these can apply to anything the user wants to specify (not only ProgressBar controls).
public double ProgressValue
{
get { return progress; }
set { progress = value / 100; }
}
I also modified the XAML markup for my window, to add the ProgressBar control inside the main window, as well as reference the one in the Taskbar.
<Window x:Class="WPF_Test.MainWindow"You can see here the Window.TaskbarItemInfo element – this handles the Taskbar contents in Windows 7, but at this point I am more interested how it is bound to a property. The ProgressValue property is set to "{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=ProgressValue}" - I am actually showing that the property I am binding to is located inside the ancestor class (WPF_Test.MainWindow – set by RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}) and the property is called ProgressValue (set by Path).
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="300" Width="300"
Loaded="Window_Loaded">
<Window.TaskbarItemInfo>
<TaskbarItemInfo ProgressValue="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=ProgressValue}" ProgressState="Normal"></TaskbarItemInfo>
</Window.TaskbarItemInfo>
<Grid x:Name="Grid1">
<ProgressBar x:Name="progressBar1" Height="59" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="256" Value="50" ValueChanged="progressBar1_ValueChanged" />
</Grid>
</Window>
You might be wondering – what is RelativeSource? This is a way to reference properties located in controls that are relative to the current element. For example, the window is relative to the ProgressBar by being its ancestor of type Window. This way, I can also search for child elements.
At this point you might also be wondering why inside the property I am setting the value of progress to the passed value divided by 100. This is because the ProgressValue property of the TaskBarItemInfo is ranged between 0 and 1, therefore I need to pass a proportional value to it, since in a regular ProgressBar the values range between 0 and 100. This can be adjusted to personal needs.
But let’s get back to binding. Now, inside the progressBar1_ValueChanged event handler (that is triggered every time the value is changed in the ProgressBar control I am using this code to set the value to the existing property:
ProgressValue = progressBar1.Value;Simple as that. Now all you need to do is run the application and see the progress bar in the Taskbar filled to 50% (I am using this pre-set value in XAML).
As you see, binding is a very important capability in WPF and once you fully understand its concept, you can easily apply it to a multitude of situations that require the developer to bind control properties and to change them depending on the state of other properties.
Opinions expressed by DZone contributors are their own.
Comments