Introduction
Welcome again! Today we'll talk about a little bit advanced topic, Data Binding. It's really useful when you've massively structured code and you've to handle a lot of data, not like our typical controls. For example:
textBox1.Text = “Hello, world!”;
Data Binding is nothing but creating a “ViewModel” class or you can name it as you wish, that actually contains the data. One more important thing, you must follow in the Data Binding control is INotifyPropertyChanged. It actually gives you an alert, when a property value is changed. Just like hey there, “I'm changed.” We'll return to it later.
Various Binding Modes
There are a number of various binding modes, as defined in the BindingMode enumeration:
- TwoWay: Changes to the UI or model automatically updates the other. This is used for editable forms or other interactive scenarios.
- OneWay: Updates the UI when the model changes. This is appropriate for read-only controls populated from data.
- OneTime: Updates the UI when the application starts or when the data context changes. This is used when the source data is static/does not change.
- OneWayToSource: Changes to the UI update the model.
- Default: Uses the default mode for the specific binding target (UI control). This differs based on the control.
Objects that take part in OneWay or TwoWay binding must implement the “INotifyPropertyChanged” interface. Thus interface requires only that the object publishes the “PropertyChanged” event:
- public class ItemViewModel : INotifyPropertyChanged
- {
- public event PropertyChangedEventHandler PropertyChanged;
- ...
- }
Listing 1
The object must fire the “PropertyChanged” event whenever the value of one of its public properties changes.
So, first of all we'd like to implement our “ViewModel” class, that will contain our data properties.
Adding a “ItemViewModel” class
Add a new class and provide it a name “ItemViewModel”.
Figure 1
Now, we need to declare our private properties what we want to do and make public get and set methods. It's really a bad idea to declare your variables public. So, we've declared it private but work with it internally public.
There are two types of “INotifyPropertyChanged” implementations. One is Non-Optimal and the other is Optimal. Let's see how the Non-Optimal implementation works first.
- public class ItemViewModel : INotifyPropertyChanged
- {
-
- private string _manufacturer;
- private string _model;
- private string _color;
- private int _year;
-
- public string manufacturer
- {
- get { return _manufacturer; }
-
- set
- {
- _manufacturer = value;
- NotifyPropertyChanged("manufacturer");
- }
- }
-
- public string model
- {
- get { return _model; }
-
- set
- {
- _model = value;
- NotifyPropertyChanged("model");
- }
- }
-
- public string color
- {
- get { return _color; }
- set
- {
- _color = value;
- NotifyPropertyChanged("color");
- }
- }
-
- public int year
- {
- get { return _year; }
- set
- {
- _year = value;
- NotifyPropertyChanged("year");
- }
- }
-
-
- public event PropertyChangedEventHandler PropertyChanged;
-
- private void NotifyPropertyChanged(string propertyName)
- {
- if (PropertyChanged != null)
- {
- PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
- }
- }
- }
Listing 2
Here, we've declare our four private properties, actually a car's attributes and most importantly in the setter whenever the value changes we call a method called “NotifyPropertyChanged“ (“manufacturer”), that fires that property changed event. And gives the name of that property. It's kind of error-prone because what we use is “Magic Strings”. It's not actually good to hard-cod a given new name of your property.
Optimal ViewModel Implementation
Now, let's see our Optimal ViewModel implementation.
- public class ItemViewModel : INotifyPropertyChanged
- {
-
- private string _manufacturer;
- private string _model;
- private string _color;
- private int _year;
-
- public string manufacturer
- {
- get { return _manufacturer; }
-
- set { this.SetProperty(ref this._manufacturer, value); }
- }
-
- public string model
- {
- get { return _model; }
-
- set { this.SetProperty(ref this._model, value); }
- }
-
- public string color
- {
- get { return _color; }
-
- set { this.SetProperty(ref this._color, value); }
- }
-
- public int year
- {
- get { return _year; }
-
- set { this.SetProperty(ref this._year, value); }
- }
-
-
-
- public event PropertyChangedEventHandler PropertyChanged;
-
- protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
- {
- if (object.Equals(storage, value)) return false;
- storage = value;
- this.OnPropertyChaned(propertyName);
- return true;
- }
-
- private void OnPropertyChaned(string propertyName)
- {
- var eventHandler = this.PropertyChanged;
- if (eventHandler != null)
- eventHandler(this, new PropertyChangedEventArgs(propertyName));
- }
- }
Listing 3
And you've noticed that it's a kinda nice reflection tool to change the name of your property, that will do nicely through all of your app. It works similarly with a Non-Optimal “ViewModel” but you must change the value of your property automatically and fire the “PropertyChanged” event whenever the value of one of its public properties changes.
Designing UI
So, our “ViewModel” implementation is okay now. Now, we'll move to design our app, that will show four properties of our “ItemViewModel” class. Let's use four TextBlocks and a Button. You can design as you wish to do so. The sample XAML UI code is given below.
- <!--TODO: Content should be placed within the following grid-->
- <Grid Grid.Row="1" x:Name="ContentRoot" Margin="19,9.5,19,0">
- <TextBlock Height="50"
- HorizontalAlignment="Left"
- Margin="10,10,0,0"
- Name="manufacturerBlock"
- Text="{Binding manufacturer,Mode=TwoWay}"
- VerticalAlignment="Top"
- Width="342" FontSize="24"/>
- <TextBlock Height="50"
- HorizontalAlignment="Left"
- Margin="10,65,0,0"
- Name="modelBlock"
- Text="{Binding model,Mode=TwoWay}"
- VerticalAlignment="Top"
- Width="342" FontSize="24"/>
- <TextBlock Height="50"
- HorizontalAlignment="Left"
- Margin="10,120,0,0"
- Name="colorBlock"
- Text="{Binding color,Mode=TwoWay}"
- VerticalAlignment="Top"
- Width="342" FontSize="24"/>
- <TextBlock Height="50"
- HorizontalAlignment="Left"
- Margin="10,175,0,0"
- x:Name="yearBlock"
- Text="{Binding year, Mode=TwoWay}"
- VerticalAlignment="Top"
- Width="342" FontSize="24"/>
- <Button Content="Update"
- Height="50"
- HorizontalAlignment="Left"
- Margin="202,443,0,0"
- Name="updateButton"
- VerticalAlignment="Top"
- Width="150"
- Click="updateBtn_Click" />
- </Grid>
Listing 4
Here, we've used the TwoWay mode, because we will update our databound UI elements in the XAML runtime.
Backend C# Coode
Now, let's look inside of our “MainPage.xaml.cs” class.
- public sealed partial class MainPage : Page
- {
- ItemViewModel _itemViewModel;
- ...
- }
Listing 5
Put this line of code at the top of our constructor. It creates an object of our “ItemViewModel” class.
-
- public MainPage()
- {
- this.InitializeComponent();
-
- Loaded += MainPage_Loaded;
- ...
- }
Listing 6
Update the constructor with the “MainPage_Loaded” method, because when you run the application it'll call the method to display the data.
Now, implement the “MainPage_Loaded” method.
-
- public MainPage()
- {
- this.InitializeComponent();
-
- Loaded += MainPage_Loaded;
- ...
- }
Listing 7
So, we created a new “ItemViewModel” object and bound our data in the “ItemViewModel” class and set the data context by calling the “setDataContext” method.
- private void setDataContext()
- {
- ContentRoot.DataContext = _itemViewModel;
- }
Listing 8
What it does is it sets up our data in the main Grid of our XAML UI. Here, “ContentRoot” is the name of our main Grid.
-
- private void setItemProperties(String manufacturer, String model, String color, int year)
- {
- _itemViewModel.manufacturer = manufacturer;
- _itemViewModel.model = model;
- _itemViewModel.color = color;
- _itemViewModel.year = year;
- }
Listing 9
It's kinda nice, that you don't need to worry about showing your data. Which is string and which is int, you don't need to bother about it. Just make a reference of your data, that's it.
When we press our Update Button, it'll do the work for us.
-
- private void updateBtn_Click(object sender, RoutedEventArgs e)
- {
- setItemProperties("Ford", "Mustang GT", "Blue", 2010);
- }
Listing 10
It calls the “setItemProperties” method and es the following data to it. Really simple, isn't it?
Running the Application
Now, if you run the application, it'll look exactly like this.
Summary
That's it. I hope you understand the basics of “DataBinding” and the “INotifyPropertyChanged Interface”. So, make your app more awesome with these features. I'll be here with some new topics soon. Until then good bye. Have a nice day.
Happy Coding!
Read the original article at:
http://bit.ly/1t2oND4