Click here to Skip to main content
15,881,092 members
Articles / Programming Languages / C#
Tip/Trick

Simple Model-View-ViewModel in Windows Forms

Rate me:
Please Sign up or sign in to vote.
4.83/5 (4 votes)
31 Jan 2013CPOL3 min read 28.8K   400   16   5
Just a tip about using data bindings in Windows Forms.

Introduction   

As soon as you are into MVVM and WPF, it is almost impossible to go back. The problem is, sometimes we have to go back. Perhaps you were escalated to work on a legacy project, or your current project requirements dictate you have to work with WinForms. However, at least for me, as soon as I got my hands back into WinForms I couldn't avoid to keep thinking in terms of Views and ViewModels. So this tip shows a quick and interesting trick to get at least some of the conveniences of developing in MVVM inside WinForms.

Note: there are frameworks specially designed for this, such as MVVM FX. However, documentation seems lacking, at best. Besides, WinForms doesn't have all the required support for a true MVVM pattern, specially for composing the View.   

But it doesn't do that bad for data binding. 

Binding to ViewModel from a Form 

The first thing is to realize that WinForms has useful data binding capabilities. I failed to notice how useful data binding was until I got into WPF. But let's not make this sin ever again. Suppose, for example, we have a ViewModel like this: 

C#
public class MainViewModel : INotifyPropertyChanged
{ 
 public event PropertyChangedEventHandler PropertyChanged;

 public bool SomePropertyThatWouldLikelyDetermineVisiblityOfAControl { get; private set; }

 ...
} 

Now, in our view, suppose we would decide to bind the visibility of a control to the suggestively named property of the ViewModel above. In WPF this would be quite trivial. Now what about WinForms? Well, it is too, if the component implements the IBindableComponent interface. If we add the  following code to the Load event of the form, we get a very pleasantly similar result: 

C#
private void MainForm_Load(object sender, EventArgs e)
{
    myControl.DataBindings.Add(new Binding("Visible", viewModel,
      "SomePropertyThatWouldLikelyDetermineVisiblityOfAControl"));      
}

However, what if the property type has nothing to do with the property we are binding? We could write some converters, such as in WPF and so on. But consider the following extension class, for a minute: 

C#
public static class BindingExtensions
{
    public static void Bind<T, U>(this IBindableComponent component, 
        Binding binding, Func<T, U> transform)
    {
        binding.Format += (sender, e) => e.Value = transform((T)e.Value);
        component.DataBindings.Add(binding);
    }

    public static void Bind(this IBindableComponent component, Binding binding)
    {
        component.DataBindings.Add(binding);
    }

    public static void Bind<T, U>(this IBindableComponent component,
        string propertyName, object dataSource, string dataMember, Func<T, U> transform)
    {
        Bind(component, new Binding(propertyName, dataSource, dataMember), transform);
    }

    public static void Bind(this IBindableComponent component,
        string propertyName, object dataSource, string dataMember)
    {
        Bind(component, new Binding(propertyName, dataSource, dataMember));
    }
}

Let's see how we can leverage this class to obtain arbitrary data binding fairly easy in our WinForms application. 

Using the code

Suppose we would like to bind the Text property of a TextBox to this boolean property. Using the aforementioned code, all we would need to do is: 

C#
private void MainForm_Load(object sender, EventArgs e)
{
 textBox.Bind("Text", viewModel, "SomePropertyThatWouldLikelyDetermineVisiblityOfAControl",
   (bool value) => value ? "Property says true" : "Property says false");
}

And so we have converted the boolean value of the ViewModel into our view's text. This is also useful if, for example, instead of enabling the visibility of a control like in the first example, we would be interested in disabling it whenever the property is true. Let's see: 

C#
private void MainForm_Load(object sender, EventArgs e)
{ 
    myButtom.Bind("Visible", viewModel, 
      "SomePropertyThatWouldLikelyDetermineVisiblityOfAControl", (bool value) => !value);
}

and now we have the negated behavior of the first example.  

The zip file attached to this article contains the entire BindingExtensions class, offering support for both the format and parse methods of the WinForms data binding framework using lambda functions. If you feel interested, feel free to take a look. You can also browse the code using CodeProject's article code browser by clicking the "Browse Code" button on the left.  

Using the full class available on the zip, we can also use lambda expressions to achieve both type-safety and, as noted in Hoangitk's comment, be used together with code obfuscators. Thus we can create a bindings using: 

C#
private void MainForm_Load(object sender, EventArgs e)  
{  
 myButton.Bind(b => b.Visible, 
   viewModel, m => m.SomePropertyThatWouldLikelyDetermineVisiblityOfAControl);

 // or even transform the bound property value using
 myButon.Bind(b => b.Visible, 
  viewModel, m => m.SomePropertyThatWouldLikelyDetermineVisiblityOfAControl,
  value => !value); // negates the value of the binding
}

Hope you will find this interesting! Smile | <img src=

Drawbacks  

Obviously this only offers very limited support for basic data binding. Perhaps a better title for this tip would be "a simple way to approximate MovelView-View-Model behavior inside Windows Forms". For instance, I am not sure if this will handle two-way binding. 

But the easiness to simply declare which control binds to which property in a ViewModel, with the ability to control how the binding is done without the need for writing hideous converter classes was already very handy for me. What do you think?   

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Engineer NAVER LABS Europe
France France
Computer and technology enthusiast, interested in artificial intelligence and image processing. Has a Master's degree on Computer Science specialized on Image and Signal Processing, with expertise on Machine Learning, Computer Vision, Pattern Recognition and Data Mining systems. Author of the Accord.NET Framework for developing scientific computing applications.

If you would like to hire good developers to build your dream application, please check out DaitanGroup, one of the top outsourcing companies in Brazil. This company, located in Brazil's Sillicon Valley but with US-based offices, has huge experience developing telecommunications software for large and small companies worldwide.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Hoangitk1-Jan-13 15:06
professionalHoangitk1-Jan-13 15:06 
Simple and useful
GeneralRe: My vote of 5 Pin
César de Souza1-Jan-13 15:40
professionalCésar de Souza1-Jan-13 15:40 
GeneralRe: My vote of 5 Pin
Hoangitk1-Jan-13 17:54
professionalHoangitk1-Jan-13 17:54 
GeneralRe: My vote of 5 Pin
César de Souza2-Jan-13 5:18
professionalCésar de Souza2-Jan-13 5:18 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.