Why WPF for automation? Databinding #1

This is the 1st article of 3 about DataBinding.
Check the 2nd here and the 3rd here.
It's clear that WPF has a better graphic and appearence, with all of those gradients, animations and so on, but what are the real benefits for a programmer ?
The Page-Switch application was a good start, but why should we learn xaml (that is also a new concept and quite hard) instead of using our loved winforms and GDI ?
I think that the best reason to learn WPF is that it permits to build easy-to-use and self-explained interfaces for operators, with really little code-writing.
Let's suppose that i wanted to display lisbox of radiobuttons, or treeview of checkbox... it would be hard to write this controls in winforms and they would have a lot of bugs inside.
That's why winforms got a lot of custom control (not free of course) around the ne.
In WPF, thanks to a pattern that separates graphics from code-behind, it's possible to have complex controls with not many troubles.
Model - View - View Model is the pattern that permit to developpers to separate physically the User Interface part from the code behind, and this is possible because of a powerful concept on wich WPF is based: DataBinding.

Basically Model - View - View Model consist in this:
Model : all the codebehind, services and so on  that permit to the application to run (like the code that was written in winforms)
View: the User Interface, all the code that we write in XAML.
View Model: this is new, this is the layer between UI and code behind, it's based on data binding and it save us a lot of code that can have a lot of bugs, and it's usually the code that connects the UI with business objects. One important fact to keep in mind is that in automation we have tons of controls to display tons of values, infact usually little scada and HMI displays timers, analogic values, alarms and some output status, but in bigger ones there are a lot of other factor too, like keeping track of values while time changes and so on. View Model permit to connect the User Interface with Objects, that can come for example from an OPC Client, with really little code.

To explain it better i'll make an example:
I want to fill a tank (here is designed really poorly) with a liquid that i select from a listbox, and i want to see the tank changing color when i change its content.
I don't want to use events and a lot of code to do this thing, also i want to define a class Liquid and a collection of them, because they can change during production, and i would like to update them easily.

So let's write the liquid class:
using System.Windows.Media;
namespace SilosSample.Data
{
    class Liquid
    {
        public string Name { get; private set; } //name of liquid       
        public LinearGradientBrush LiquidColor { get; private set; } //color
       

        public Liquid(string name, GradientStopCollection _gradStopCollection)
        {
            this.Name = name;
            this.LiquidColor = new LinearGradientBrush(_gradStopCollection);
        }
    }
}


Then fill the collection (in reality members would be taken from a database, with more parameters than a name and a color)
using System.Collections.ObjectModel;
using System.Windows.Media;
using SilosSample.Data;
namespace SilosSample.ViewModel
{
    class LinearGradientCollection : ObservableCollection
    {
        public LinearGradientCollection()
        {
            this.Add(EmptyCilinder());
            this.Add(Water());
            this.Add(OrangeLiquid());           
        }
        private Liquid EmptyCilinder()
        {
            GradientStopCollection gradStopCollection = new GradientStopCollection();      
            gradStopCollection.Add( new GradientStop(Colors.LightGray,0));
            gradStopCollection.Add(new GradientStop(Colors.Black, 0.992));
            gradStopCollection.Add(new GradientStop(Colors.DarkGray, 0.125));
            gradStopCollection.Add(new GradientStop(Colors.Gray, 0.802));
            return new Liquid("Empty Cilinder", gradStopCollection);
        }
        private Liquid Water()
        {
                GradientStopCollection gradStopCollection = new GradientStopCollection();
                gradStopCollection.Add(new GradientStop(Colors.LightCyan, 0));
                gradStopCollection.Add(new GradientStop(Colors.DarkBlue, 0.992));
                return new Liquid("Water", gradStopCollection);
        }
        private Liquid OrangeLiquid()
        {
                GradientStopCollection gradStopCollection = new GradientStopCollection();
                gradStopCollection.Add(new GradientStop(Colors.LightCoral, 0));
                gradStopCollection.Add(new GradientStop(Colors.Orange, 0.992));
                return new Liquid("Orange liquid", gradStopCollection);
        }
    }
}

And now i want to connect(to bind) my user interface to the collection.
this is done in this way:
define a datacontext (it's the datasource, in this case my collection of colors) in the codebehind  for the listbox:
public partial class MainWindow : Window
    {     
        public MainWindow()
        {
            InitializeComponent();
            lstSelectColor.DataContext = new LinearGradientCollection();
//my collection    
        }
    }

Then write the User Interface and bind the properties that you want to control directly with XAML:
in this case i wanted that my listbox contains the collection (so datasource was in bind with all the datacontext), i wanted to display only the name (displayMemberPath is always the same as old one), and i wanted to synchronize the current element with the rest of the window, so i can update my controls without writing a single line of code.
Then to fill the silos there, i just need to bind the property "Fill" at the selected item of the listbox, just as it's written in the code.


This is really a simple example, but it's amazing how powerful it is WPF and how little code you have to write to obtain sophisticated controls.
In a future post i'll cover also the interface "INotifyPropertyChanged", that permit to update an item in a collection and also the items in bind with it (example: i have a collection of silos and i want to update the color of one of them).

As usual i add the complete solution:http://www.megaupload.com/?d=IQUX2NVX

To see more about ObservableCollection, INotifyPropertyChanged and normal collections, see this post: http://www.codeproject.com/KB/silverlight/SLListVsOCollections.aspx

No comments: