Data Binding (part 1, advanced), WPF

I was studying the “Google Authentication” as I plan to write a post about it. But then I came across the WPF data binding, which I was avoiding so far, because code pieces are not easy to display in posts due to their complexity. The “Google Authentication” source code will use WPF data binding. It therefore makes sense to post about WPF data binding first. Newbies have problems with WPF. It can be quite overwhelming at the beginning. This post is not covering the basics. I expect them to be known already. I will only concentrate on some data binding with TextBoxes today.

Have a look at the XAML:

<Window x:Class="WpfDatabinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        
        Title="MainWindow" Height="194" Width="374">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <Label Grid.Column="0" Grid.Row="0" Content="Value1, Init only" VerticalAlignment="Center" />
        <TextBox Grid.Column=" 1" Grid.Row="0" VerticalAlignment="Center" Text="{Binding Value1, Mode=OneTime}" />

        <Label Grid.Column="0" Grid.Row="1" Content="Value1, OneWay" VerticalAlignment="Center" />
        <TextBox Grid.Column=" 1" Grid.Row="1" VerticalAlignment="Center" Text="{Binding Value1, Mode=OneWay}" />        

        <Label Grid.Column="0" Grid.Row="2" Content="Value2, OneWayToSource" VerticalAlignment="Center" />
        <TextBox Grid.Column=" 1" Grid.Row="2" Text="{Binding Value2, Mode=OneWayToSource}" VerticalAlignment="Center" />

        <Label Grid.Column="0" Grid.Row="3" Content="Value3, OneWay" VerticalAlignment="Center" />
        <TextBox Grid.Column=" 1" Grid.Row="3" Text="{Binding Value3, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />
        
        <Label Grid.Column="0" Grid.Row="4" Content="Value3, TwoWay" VerticalAlignment="Center" />
        <TextBox Grid.Column=" 1" Grid.Row="4" Text="{Binding Value3, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />

        <Label Grid.Column="0" Grid.Row="5" Content="Value3, TwoWay" VerticalAlignment="Center" />
        <TextBox Grid.Column=" 1" Grid.Row="5" Text="{Binding Value3, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />
    </Grid>
</Window>

Instead of assigning simple text literals to the TextBoxes like: Text=”Hello World!”, we assign binding definitions in curly brackets. For instance: Text=”{Binding Value2, Mode=OneWayToSource}”
In this case we connect the property “Value2” with the TextBox text. The Mode tells the binding direction:

Mode

The UpdateSourceTrigger=PropertyChanged implies that the binding source class has implemented the interface INotifyPropertyChanged, which requires the event implementation called PropertyChanged. When the program raises this event with the correct property name, which is also defined in the XAML file, then the binding will refresh the GUI element.

And here is the program. Create a BindingClass instance and assign it to the current window DataContext. There is nothing else to do. The rest is taken care of by the .Net Framework and compiler. WPF is quite abstract. A lot of code is generated out of the XAML files. You cannot see the generated code without pressing the icon “Show All Files” in the Solution Explorer. What is important to know is that we are mainly looking at partial files (here: “public partial class MainWindow : Window”). The rest is auto-generated source code.

using System.Windows;

namespace WpfDatabinding {
   public partial class MainWindow : Window {

      public MainWindow() {
         InitializeComponent();
         DataContext = new BindingClass();
      } //

   } // class
} // namespace
using System;
using System.ComponentModel;
using System.Timers;

namespace WpfDatabinding {
   public class BindingClass : INotifyPropertyChanged {
      public event PropertyChangedEventHandler PropertyChanged;

      private string _Value1 = "Value1 XX:XX:XX";
      private string _Value2 = "Value2 XX:XX:XX";
      private string _Value3 = "Value3 XX:XX:XX";

      public string Value1 { get { return _Value1; } set { _Value1 = value; RaiseEvent("Value1"); } }
      public string Value2 { get { return _Value2; } set { _Value2 = value; RaiseEvent("Value2"); Console.WriteLine(_Value2); } } // event has no effect
      public string Value3 { get { return _Value3; } set { _Value3 = value; RaiseEvent("Value3"); } } // event has effect on TwoWay

      public BindingClass() {
         Timer lTimer = new Timer(1000.0);
         lTimer.Elapsed += new ElapsedEventHandler(Timer_Elapsed);
         lTimer.Start();
      } // constructor

      void Timer_Elapsed(object sender, ElapsedEventArgs e) {
         string lNow = DateTime.Now.ToString("HH:mm:ss");
         Value1 = "Value1 " + lNow;
      } // 

      private void RaiseEvent(string xPropertyName) {
         var lEvent = PropertyChanged;
         if (lEvent == null) return;
         lEvent(this, new PropertyChangedEventArgs(xPropertyName));
      } //

   } // class
} // namespace

The BindingClass is straight forward. There are no events that are triggered by the GUI. The separation of XAML and program code is a pretty cool approach.
There are three properties: Value1, Value2 and Value3.
Value1 is constantly written to by a timer event that is raised each second.
Value2 is only receiving values from the GUI, because the corresponding TextBox is using Mode=OneWayToSource. This does not print anything in the GUI, hence I added the Console.WriteLine(_Value2) statement. Check the output there. The statement RaiseEvent("Value2") has no impact, writing to a TextBox would be the wrong direction for this mode.
And RaiseEvent("Value3") only impacts TwoWay TextBoxes, but not on the OneWay TextBox.
Play with the textboxes and see what reacts on what. My hint is that the last three TextBoxes are the most interesting ones.

WpfDataBinding

example output on the console window:
What happens with Value 2 ?

Advertisements

About Bastian M.K. Ohta

Happiness only real when shared.

Posted on February 20, 2014, in Advanced, C#, DataBinding, WPF and tagged , , , , , , , . Bookmark the permalink. Leave a comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: