Sunteți pe pagina 1din 6

3/10/2014

MVVM in Windows Forms | Einar Ingebrigtsens Playground

Einar Ingebrigtsens Playground


A journey in software development
AUG 31 2010

2 COMMENTS
BY EINAR INGEBRIGTSEN .NET, C#

MVVM in Windows Forms


Not everyone has the luxury of jumping on new technologies, it can be historical reasons, dont
have time to learn, deployment reasons or flat out you simply dont like anything new
.
Anyways, I was doing a codereview on a project last week, which was written in Windows
Forms. The developers had some pain, Windows Forms being one of them and a constant
feeling that they were barking up the wrong tree when using Windows Forms. Its been a couple
of years since my last Windows Forms project, and I must admit I remember the feeling of
constantly banging my head against the wall without getting the code quality I wanted when
doing UI.
One of the things I saw that the project could benefit from, was unit testing to help them fight
problems with regression, and get a constant quality indicator on the project. Having done a lot of
WPF and Silverlight over the years and leaving Windows Forms behind, it just felt bad not having
a proper UI pattern and Im loving MVVM and the way it works the simplicity of it. So I
decided to do a spike, how could one implement MVVM in Windows Forms and get all the
niceness of testability and full separation.
Keep in mind, I havent done a full implementation of a framework or anything, just the basics to
get started. The one thing I wanted was to be able for the view (Form or UserControl) to be able to
observe changes from a ViewModel. Windows Forms does in fact recognize the interfaces we are
so familiar with from WPF and Silverlight (INotifyPropertyChanged and
INotifyCollectionChanged), so it was just a matter of figuring out how to get the ViewModel
easily accessible in the designer in Windows Forms. I came up with something called
ViewModelBindingSource. A very simple component that can be dragged onto the designer
surface:
1
2

public class ViewModelBindingSource : BindingSource


{

http://ingebrigtsen.info/2010/08/31/mvvm-in-windows-forms/

1/6

3/10/2014

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

MVVM in Windows Forms | Einar Ingebrigtsens Playground

public ViewModelBindingSource(IContainer container)


: base(container)
{
}
private object _viewModel;
private Type _viewModelType;

[Category("MVVM"), DefaultValue((string)null), AttributeProvider(typeof(IList


public Type ViewModel
{
get { return _viewModelType; }
set
{
SuspendBinding();
_viewModelType = value;
_viewModel = Activator.CreateInstance(_viewModelType);
Add(_viewModel);
MoveFirst();
ResumeBinding();
}
}
public override object this[int index]
{
get
{
return _viewModel;
}
set
{
base[index] = value;
}
}
}

The next thing I wanted to accomplish, was the ability to hook up Commands for Buttons and
such, supporting the ICommand interface found in WPF. I came up with a
CommandExtenderProvider:
1
2
3
4
5
6
7
8
9
10
11
12

[ProvideProperty("Command", typeof(Button))]
public class CommandExtenderProvider : Component, IExtenderProvider
{
private readonly Dictionary _buttonsWithCommands;
private readonly List _uninitializedButtons;
public CommandExtenderProvider()
{
_buttonsWithCommands = new Dictionary();
_uninitializedButtons = new List();
}
public bool CanExtend(object extendee)
{

http://ingebrigtsen.info/2010/08/31/mvvm-in-windows-forms/

2/6

3/10/2014

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

MVVM in Windows Forms | Einar Ingebrigtsens Playground

return extendee is Button;


}
private BindingSource _viewModelSource;
[Category("MVVM")]
public BindingSource ViewModelSource
{
get { return _viewModelSource; }
set
{
_viewModelSource = value;
InitializeUninitializedButtons();
}
}
private void InitializeUninitializedButtons()
{
foreach( var button in _uninitializedButtons )
{
var commandName = _buttonsWithCommands[button];
SetCommand(button, commandName);
}
_uninitializedButtons.Clear();
}
[Editor(typeof(CommandEditor), typeof(UITypeEditor))]
public string GetCommand(Button button)
{
if (!_buttonsWithCommands.ContainsKey(button))
{
return null;
}
var command = _buttonsWithCommands[button];
return command;
}
public void SetCommand(Button button, string commandName)
{
_buttonsWithCommands[button] = commandName;
if (null == ViewModelSource ||
null == ViewModelSource.Current)
{
_uninitializedButtons.Add(button);
return;
}
var property = ViewModelSource.Current.GetType().GetProperty(commandName);
if (null != property)
{
var command = property.GetValue(ViewModelSource.Current, null) as ICommand;
if (null != command)
{
button.Enabled = command.CanExecute(null);
command.CanExecuteChanged += (s, e) => button.Enabled = command.CanExecute(
button.Click += (s, e) =>
{
if (command.CanExecute(null))
{
command.Execute(null);

http://ingebrigtsen.info/2010/08/31/mvvm-in-windows-forms/

3/6

3/10/2014

67
68
69
70
71
72

MVVM in Windows Forms | Einar Ingebrigtsens Playground

}
};
}
}
}
}

In the designer, youll get two new components you can then drag onto your Windows Forms
design surface:

Simply start by dragging in the ViewModelBindingSource and


look in the Properties of it. Under the MVVM category, youll find the property ViewModel a
dropdown were you can select the ViewModel.

If you then drag onto the design surface a TextBox


that you want to have databound to a property in the ViewModel and look in the Properties
window for the TextBox. There youll find your ViewModelBindingSource, expanding it will
show all the properties available in the ViewModel:

For commands, we need the


CommandExtenderProvider. That too can be dragged onto the surface. It has a property for
selecting the ViewModelBindingSource:
http://ingebrigtsen.info/2010/08/31/mvvm-in-windows-forms/

4/6

3/10/2014

MVVM in Windows Forms | Einar Ingebrigtsens Playground

Now you can add a button to the surface and go to


properties, youll find a property called Command. There you can select the command you want
to be executed during Click.

There is still a bunch of things to be desired in order


for this to fully support all aspects of MVVM. But it proves its possible to think in this way, even
though your technology is not necessarily state of the art.
Hope anyone finds this interesting.
The source code can be found here
(http://dl.dropbox.com/u/5342359/Ingebrigtsen/WindowsForms_MVVM.zip).

2 thoughts on MVVM in Windows Forms


concept says:

October 15, 2012 at 6:33 am


Thanks for your article, its quite helpful for me, having now the same downshift from
SL/WPF to WinForms.
If i could ask some enhancement, then some more comments just in the code.
Regards. concept
Reply
Einar Ingebrigtsen says:
Hi,
thanks.. Sorry for the insane response time from me.
Are there any specific part of the code that seems unclear?

November 4, 2012 at 10:17 am

Reply
http://ingebrigtsen.info/2010/08/31/mvvm-in-windows-forms/

5/6

3/10/2014

MVVM in Windows Forms | Einar Ingebrigtsens Playground

Blog at WordPress.com. | The Chunk Theme.


Follow

Follow Einar Ingebrigtsens Playground


Powered by WordPress.com

http://ingebrigtsen.info/2010/08/31/mvvm-in-windows-forms/

6/6

S-ar putea să vă placă și