Showing posts with label WPF. Show all posts
Showing posts with label WPF. Show all posts

Thursday, May 5, 2011

Binding data from the ViewModel to the Wpf Menu control

Databinding the Menu Control in wpf to a viewmodel can require a little bit of effort. As a menu control can contain hierarchical data, you must think of a data model to represent your menu items upfront, so I've decided to write a little about it. But before we dive into the meat and potatoes, lets try the basics first.

Lets see what a simple statically defined menu control looks like and then we'll transform this into a data model we can bind to from our viewmodel.

The statically defined menu :
<Grid>
    <Border VerticalAlignment="Top" Height="25" BorderThickness="0,0,0,1" 
            Background="#FFE4E2E2" BorderBrush="#FFA0A0A0">
        <Menu Height="25" VerticalAlignment="top">
            <MenuItem Header="_File">
                <MenuItem Header="New/Open project"/>
                <MenuItem Header="Save"/>
                <MenuItem Header="Exit"/>
            </MenuItem>
            <MenuItem Header="_Help">
                <MenuItem Header="About us"/>
            </MenuItem>
        </Menu>
    </Border>
</Grid>

When you run the above piece of code, this is what you will see:


Notice that each MenuItem is a HeaderedItemsControl. This is simply an ItemsControl with a Header.

Because each MenuItem is a HeaderedItemsControl, this allows our Menu to have an unlimited number of nesting as each Item has a header ( a label, the title you see displayed in the menu) and then an items collection (the sub menu items). If we wanted to see a qiuck example, this can be easily represented declaratively as follows :

<Menu>
      <MenuItem Header="_File">
           <MenuItem Header="New/Open project"/>
...
See how each MenuItem can in turn contain nested MenuItems, and a Header property is set to the title we want to display.

To bind the Menu control from our viewmodel, we need to be able to set the bindings for each menu items header and additionally we'll need to set a command argument so that we can identify the item clicked.

In order to achieve this we'll have to set bindings through the ItemContainerStyle. This will allow us to target the element generated for each MenuItem so that we can pass the Header value and additionally a command argument value to identify the item. By using a style element in ItemContainerStyle, we can set the TargetType to MenuItem as in the example code below, and the property setters will apply the value bindings to each MenuItem. Perfect.

<Menu ItemsSource="{Binding MenuItems}">
    <Menu.ItemContainerStyle>
        <Style TargetType="MenuItem">
            <Setter Property="Command" Value="{Binding Command}" />
            <Setter Property="CommandParameter" 
                       Value="{Binding CommandParameter}" />
            <Setter Property="Header" Value="{Binding Header}" />
            <Setter Property="ItemsSource" Value="{Binding Items}"/>
        </Style>
    </Menu.ItemContainerStyle>
</Menu>

Let's quickly walk through the piece of xaml above. As you can note, the Menu control itself is bound to a MenuItems collection exposed in our viewmodel.

Xaml :
<Menu ItemsSource="{Binding MenuItems}">

ViewModel:
public ObservableCollection<FileMenu> MenuItems
{
 get
 {
  return (_menuItems = _menuItems ??
   new ObservableCollection<FileMenu>());
 }
}

Xaml :
<Style TargetType="MenuItem">
            <Setter Property="Command" Value="{Binding Command}" />
            <Setter Property="CommandParameter" 
                       Value="{Binding CommandParameter}" />
            <Setter Property="Header" Value="{Binding Header}" />
            <Setter Property="ItemsSource" Value="{Binding Items}"/>
        </Style>

The above xaml binds to each item in the MenuItems ObservableCollection our viewmodel exposes.

Model:
public class FileMenu : ModelBase
{
        ...
 public string Header { get; set; }

 public string CommandParameter { get; set; }

 public ICommand Command
 {
  get
  {
   return (_command = _command ??
    new DelegateCommand<string>(
     OnMenuItemClick, (x)=> IsEnabled));
  }
 }
...
 public ObservableCollection<FileMenu> Items
 {
  get
  {
   return (_items = _items ??
    new ObservableCollection<FileMenu>());
  }
 }
 ...
}

The FileMenu class above represents each item in the MenuItem's collection. As you can see, it's a very simple object with just the needed properties. Note also that each item can also contain child items, this allows us to build a hierarchical menu dynamically in code. If we go back to look at the previous xaml listing above, this is exactly what the following line does :

<Setter Property="ItemsSource" Value="{Binding Items}"/>

The ItemsSource property is exposed by the MenuItem control. In this manner, if each FileMenu Item contains submenu items in turn, they will be bound. Nice!

We now have a perfectly bindable hierarchical menu and what more, it follows the MVVM pattern with clear separation.

Be sure to check out the sample application since code speaks for itself!

Download the sample code

Friday, April 29, 2011

Getting the Most Out of the Winforms PropertyGrid Control in WPF

The PropertyGrid control has been missing in WPF since it's release and sadly it's still missing! There have been various attempts by third parties to provide one and I cant speak for the commercial offerings but I find the ones in the open source space to be quite lacking and incomplete. Most projects I found on codeplex are still in beta!

I really like the api exposed by the original PropertyGrid which I have been using for years now but it's a Winforms control. This presents some problems. The main issue for me with the Winforms version of the PropertyGrid is that it's not styleable. So it means that I'll have some inconsistency in my UI and it will stick out as shabby and odd.

Below is a screenshot of the PropertyGrid bound to a simple “Person” object, that exposes a complex type Address and a vehicle collection property.


As old as it may look, it works so well and does it job so nicely! I love this control. In the end, I've decided to use this in my Wpf application regardless of the oddity it brings. Clearly, functionality is a lot more important and since beauty lies in the eyes of the beholder, it's a subjective matter. And writing a brand new native Wpf PropertyGrid control is out of the question.

Looks apart, think of the great things this control can do. You practically bind your objects to it and it will list them in a neat grid, categorized, with many builtin editors for color editing, navigating for images, browsing and editing collections using the builtin CollectionEditor etc. And if this is not enough you can write simple extensions with your own custom editors. Indeed this control is a gem!
Update 4/30/2011
It seems since we are referencing a Winforms library, in particular System.Windows.Forms, our client app is forced to reference the fatter .NET 4.0 version versus just the slimmer .NET 4.0 client profile which is the default. 
It's not such a big con, but most certainly something to consider. I've left some more instructions at the bottom of this post.
One thing in particular that I've done is to wrap it up in a Custom Wpf Control because in order to use the Winforms version in Wpf, we'll need to :
  1. Interop via WindowsFormsHost (as easy as eating cake)
  2. We'd like to bind our ViewModel to the PropertyGrid directly from the View declaratively. This will allow us to avoid tight coupling with our ViewModel.
Here's what the custom controls template looks like :

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:WpfLab2.Controls"
                   xmlns:o="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms">
    <Style TargetType="{x:Type local:WpfPropertyGrid}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:WpfPropertyGrid}">
                    <Grid>
                        <WindowsFormsHost x:Name="host">
                            <o:PropertyGrid x:Name="propertyGrid1"/>
                        </WindowsFormsHost>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

Minus the namespaces and the common style declarations you'll likely do for any templating requirement, it's fairly simple. All we need is to nest the Winforms PropertyGrid inside a WindowsFormsHost.

<Grid>
    <WindowsFormsHost x:Name="host">
        <o:PropertyGrid x:Name="propertyGrid1"/>
    </WindowsFormsHost>
</Grid>

That's pretty much all of the code. Simple indeed. The Wpf Control itself consists of a single dependency property minus a small plumbing effort. Attached to this article I include a sample application containing the control, so you can get a hang of how it works. Our View itself that consumes the PropertyGrid, just comes down to a single line of code that includes the Custom control binding to a property in the ViewModel declaratively eg:

 <local:WpfPropertyGrid SelectedObject="{Binding PersonItem, Mode=TwoWay}" />

See! Now powered with such a fantastic control you can provide easy editing of objects in your application and maintain your MVVM pattern. I love it.

Make sure you also read the following resource on msdn if your new to the PropertyGrid. It provides all the basics you'll need to know to get you up and running quickly.

http://msdn.microsoft.com/en-us/library/aa302326.aspx (Basics about the PropertyGrid)
http://msdn.microsoft.com/en-us/library/ms742875.aspx (About hosting winforms in wpf)

The sample application included is a basic example using a single person object that in turn has a complex property and a collection property. Once you edit the properties and hit the Ok button, it will display the changes in the object via a messagebox.

Nothing fancy, but you can see some simple mvvm, creation of a simple custom value converter for the complex type “Address” exposed as a property and a the creation of a simple collection editor to allow editing the “Vehicles” collection property. Just enough to get you started.

Update: 4/30/2011
A gotcha I forgot to mention is that you'll have to reference System.Windows.Forms which resides in the System.Windows.Forms assembly. The PropertyGrid control resides in this dll. When trying to reference this library from the project references dialog, you won't find it in the list of available dlls. That's because by default your project is using the .Net 4.0 client profile, so go in your project properties window and change it from .Net 4.0 client profile to .Net 4.0. After this step you can try referencing the dll again and it will be in the list.

The Microsoft .NET Framework 4 Client Profile provides a subset of features from the .NET Framework 4. The Client Profile is designed to run client applications and to enable the fastest possible deployment for Windows Presentation Foundation (WPF) and Windows Forms technology. Application developers who require features that are not included in the Client Profile should target the full .NET Framework 4 instead of the Client Profile.
Update: 5/25/2011
I was able to change the target framework back to the default Client profile after referencing System.Windows.Forms ; It seems this is already in the Client profile. What will throw you off is if your referencing System.Design.dll which will require the Full version of .NET. One typical requirement will arise for you when developing custom TypeEditors because most of the existing type editors are in the System.Design dll. Still thankfully, my needs for custom type editors was pretty basic and I got away developing one from scratch ( inheriting TypeEditor).

I found that not setting height and width explicitly for the control makes its load time slow and at most awkward even. The fix is to be explicit with the height and width. This must be due to layout differences between WPF and Windows Forms. The following article on msdn has the meat and potatoes.

http://msdn.microsoft.com/en-us/library/ms744952.aspx

So, in case its not clear, when using the control, this is what you want to attempt :

<my:WpfPropertyGrid SelectedObject="{Binding PersonItem}" Width="290" Height="350">
            </my:WpfPropertyGrid>

Notice the explicit Width and Height above. Now the speed should be super fast! Keep reading the article on msdn I link to above, it has some pretty good information.

And a small correction to the article, it's not entirely true that you cannot style the property grid. You can do some basic styling of the Winforms PropertyGrid. What you cannot do is enjoy a complete designer experience like you can currently with WPF controls. So, it's not as traggic as I made it sound.

Download the sample application

Tuesday, April 26, 2011

Custom popup and windows in WPF the MVVM way

In WPF, using the regular window control to launch child windows makes MVVM and separating a View concern from the ViewModel very difficult.

The problem:
The window control works nicely as a shell for your application, however, launching child windows is problematic because the window control cannot be defined in xaml unless as the root element.
So, if you wanted to launch child windows inside a parent window, you lose the ability to declare these in xaml. This loss means you will not be able to bind to properties in your ViewModel from the view for the purpose of opening/closing a window. Instead you end up doing this imperatively in code which means more code, more thought, more work.

Following is what you end up doing in the most minimalistic cases.

MyWindow window = new MyWindow();
window.ShowDialog();

Adding code such as the above means you are forced to make your ViewModel create instances of your Window and launch them when needed. Clearly something you will not appreciate during testing and since this will provide a tight coupling to a Window control in your ViewModel, it is useless to your tests and eventually breaks your pattern.

What would have been nice instead is if we could do the following :

<my:ModalDialogPopup IsOpen="{Binding FirstPopupIsOpen, Mode=TwoWay}"/>

If we could define our window declaratively in Xam as above, then we use the databinding capabilities in WPF and bind to an FirstPopupIsOpen property in our ViewModel, which is what we are after but sadly not currently possible.

The solution 1: A custom Control that behaved like a Window
Writing a custom control was pretty simple as we make use of the existing Popup control in Wpf. The popup control is pretty wild and requires taming but solves this problem.

Some reasons to design our solution around the existing Popup control:
  1. The popup control is designed to stay always ontop, which has it's pitfalls but it solves more problems than it brings. More specifically we will want the ability to hide the content under the popup while the popup is in view.
  2. The popup control can be positioned in so many ways, however what we are after is the ability to define a set of Left, Top coordinates and this is supported out of the box.
  3. The popup control supports a few animations out of the box. This means we can apply a nice sliding or a fade effect with zero effort.
  4. The popup control can contain child controls obviously. This is great and serves our purpose very well.
  5. Enjoy the beauty of an adorner masking the background beneath the ModalDialogPopup.
The solution we end up with is a control like the following :

<my:ModalDialogPopup IsOpen="{Binding FirstPopupIsOpen, Mode=TwoWay}">
            <my:ModalDialogPopup.HostedContent>
                <ContentControl>
                    <Grid Height="200" Width="300">
                        <TextBlock VerticalAlignment="Center" 
                             HorizontalAlignment="Center" FontSize="20">
                            This is the first modal popup
                        </TextBlock>
                    </Grid>
                </ContentControl>
            </my:ModalDialogPopup.HostedContent>
        </my:ModalDialogPopup>

One inherent problem I had not considered while writing this control is that just like the Window control, even with a custom popup control, the limitation to not being able to nest a popup in another popup existed. That's because when showing the child, we are forced to hide the parent for technical reasons that exist in the popup control only(the popup control will always be the top most control).

That means if the parent is larger than the child in dimention, portions of controls in the parent will show and interaction with those pieces becomes possible. When a child popup is launched, we want it to behave as a modal window, so it shouldn't be able to interact with controls in popups beneat it. Sadly the adorner cannot help us here as it cannot cover the “Always ontop” popup.


Ofcourse, the solution to deal with this limitation is to hide the parent when the child is in view, which doesn't help the nesting because if the parent is hidden, then the child will be hidden too! I guess there is a good reason why the Window control in WPF does not allow nesting! Too bad I had to discover this at my own expense.

Even with this shortcomings, in most cases, you can workaround the nesting limitation by designing your solutions with this drawback in mind.

As you can note from the piece of xaml code in the previous code listing above, we have a control that can be defined in our view declaratively that takes content via the HostedContent template. We can also set a Title, and content in it's HostedContent template. In the previous code listing, everytime the property FirstPopupIsOpen evaluates to “true” in our ViewModel, the popup will open.

By default the custom popup provides an OK and Cancel button whose caption/visibility you can set. If you need more customizations you can very well customize its template by providing a custom style. Attemping to supply custom styling is quite simple because the default markup we use is plain and this is intentional since styling is subjective and a trival matter. This enables you to provide custom styling of your own without fighting your way through heavy use of xaml.

If you take a look at the code listing below, all we have is a 3 row grid, one holding the title, the second holding the content you define in the HostedContent template and the last row to hold the OK and Cancel buttons. Simply put, you are in control of the styling and the default style template is prive of any bloated styling markup to distract you.

<ResourceDictionary 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:WpfPopup.Controls">
    <Style TargetType="{x:Type local:ModalDialogPopup}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate 
                     TargetType="{x:Type local:ModalDialogPopup}">
                    <Popup x:Name="dialog" AllowsTransparency="True">
                        <Grid x:Name="content">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="20"/>
                                <RowDefinition Height="*"/>
                                <RowDefinition Height="20" />
                            </Grid.RowDefinitions>
                            <TextBlock Grid.Row="0" x:Name="title" />
    <!-- the hosted content -->
                            <ContentPresenter x:Name="contentHost" 
                                Grid.Row="1" Margin="5"/>
                            <StackPanel Grid.Row="2" Orientation="Horizontal" 
                                HorizontalAlignment="Right">
                                <Button Content="Ok" x:Name="buttonOK" 
                                  MinWidth="100" Margin="0,0,5,0" />
                                <Button Content="Cancel" x:Name="buttonCancel" 
                                   MinWidth="100" Margin="0,0,5,0" />
                            </StackPanel>
                        </Grid>
                    </Popup>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

And here it is when popped open in the example solution attached to this post :


It's actually quite a minimal control without any bells and whistles and leave the responsibility of styling it in your hands, any way you want. Notice the adorner masking the background and the convenient Ok/Cancel buttons. It's so much simpler to use and easy to test. The amount of work need to set this up compared to a window control (solution 2 below) is minimal.

Surely there is some value for such a control but it is most definitely not a resonable replacement to the Window control entirely, as far as launching child windows is concerned.

Fortunately, the needed work to decouple the existing Window control from the ViewModel could very well be done with a simple interface contract, which brings us to the next solution.

Solution 2 : Decoupling the Window control from the ViewModel
This solution relies on dependency injection to provide proper decoupling of the Window control from the viewmodel. So, we'll need a dependency injection container. You may use any at this point, I'll be using Microsofts Unity. This will also make it a breeze to inject a stub in place of the Window control when Unit testing.

First, let's look at what we're going to construct. It's going to be a series of dialogs. The main Window, and 2 child windows.

The main window :

A child window launched from the main window above :


And finally another child window launched from the child window above :

Ok, now that we know what we are building, lets start. The procedure is simple. We'll start by defining the common functionality we'd normally use from the Window Control in our ViewModel by throwing it into an interface.

public interface IChildWindow
{
 void Close();
 bool? ShowDialog();
 void SetOwner(object window);
 bool? DialogResult { get; set; }
}

We do this for each View that is a window control. The reason is simple, in order to decouple the window from the viewmodel, what we are going to do is use constructor injection. By injecting this dependency in the constructor we can ensure easy substitution with fake stubs during testing and everything will just work.

Let's also decouple the window we plan to launch by adding yet another interface :
public interface IChildWindowNested
{
 void Close();
 bool? ShowDialog();
 void SetOwner(object window);
 bool? DialogResult { get; set; }
}

And finally, the viewmodel:

public class ChildWindowViewModel
{
 private readonly IChildWindow _childWindow;
 private readonly IChildWindowNested _childWindowNested;
 private ICommand _okCommand;

 private ICommand _openCommand;

 public ChildWindowViewModel(IChildWindow childWindow,
    IChildWindowNested childWindowNested)
 {
  _childWindow = childWindow;
  _childWindowNested = childWindowNested;
 }

 public ICommand OpenCommand
 {
  get
  {
   return _openCommand ?? (_openCommand =
    new DelegateCommand(OpenClick));
  }
 }

 public ICommand OkCommand
 {
  get
  {
   return _okCommand ?? (_okCommand =
    new DelegateCommand(OkClick));
  }
 }

 private void OpenClick()
 {
  _childWindowNested.SetOwner(_childWindow);
  _childWindowNested.ShowDialog();
 }

 private void OkClick()
 {
  _childWindow.DialogResult = true;
  _childWindow.Close();
 }
}

As you can notice in the above class, we are passing 2 interfaces in the constructor. The first is the window using this viewmodel : ChildWindow.xaml and the second is the window it will launch : ChildWindowNested.xaml

The relationship between these two windows is a typical parent child relationship, ChildWindow.xaml is the parent, while ChildWindowNested.xaml is the child being launched.

The reason we pass IChildWindow, the parent window in this case is because :
  1. We need to tell the child Window we are launching who it's owner is. That way we can nicely position the child window relative to it's parent.
  2. As this is the viewmodel of ChildWindow.xaml, we will also want to handle closing this parent window when it's Ok and Cancel buttons are clicked.
The reason we pass IChildWindowNested, the child window we are launching is because:
  1. We want to launch this dialog based on an action in ChildWindow.xaml
  2. To decouple the window from the viewmodel, because we will be using dependency injection to set up this dependency on the window control.

Now the codebehind for ChildWindow.xaml :

public partial class ChildWindow : Window, IChildWindow
{
 private readonly IUnityContainer _container;

 public ChildWindow()
 {
  InitializeComponent();
  _container = UnityContainerResolver.Container;
  var childWindowNested = 
                             _container.Resolve<IChildWindowNested>();

  DataContext = new ChildWindowViewModel(this
                                                childWindowNested);
  Closing += ChildWindowClosing;
 }

 #region IChildWindow Members

 public void SetOwner(object window)
 {
  Owner = window as Window;
 }

 #endregion

 private void ChildWindowClosing(object sender, CancelEventArgs e)
 {
  e.Cancel = true;
  Visibility = Visibility.Hidden;
 }
}

We can setup the viewmodel binding to the DataContext in several ways however doing this in the codebehind of the view as in the sample code above is the most flexible of all solutions especially if your moving beyond the typical blog post samples.

At the end of the day, it's only a matter of opinion and what's important is that there is no dependency impeding you from testing your application. And ofcourse that it does not break your pattern. In our case, it's both convenient as we want to pass a reference of the current window to the viewmodel and at the same time, we want to do it in a very decoupled way to help us test our viewmodel.

Also note that we are hooking into the closing handler and cancelling the default close behavior of the Window control. That's because once a window is closed, we cant reopen it and we'll need to create a new instance of the window.
Certainly this depends on your use case. For me, my requirements are such that I need to reuse the window being closed. This works nicely.

What about dependency injection and how is our Unity container setup ? It's quite simple in this case. For this sample code, I just created a singleton that registers all dependencies with the container :

public class UnityContainerResolver
{
 private static IUnityContainer _container;

 private UnityContainerResolver()
 {
 }

 public static IUnityContainer Container
 {
  get
  {
   if (_container == null)
   {
    _container = new UnityContainer();
    RegisterTypes();
   }
   return _container;
  }
 }

 static void RegisterTypes()
 {
  _container.RegisterType<IMainWindow, MainWindow>();
  _container.RegisterType<IChildWindow, ChildWindow>();
  _container.RegisterType<IChildWindowNested, 
                                                    ChildWindowNested>();
 }
}

That's it. By registering dependencies with a dependency container, it becomes so easy to inject fakes in our viewmodel in place of the real object. In our case, when testing, we can make a different registration by mapping to our fake mock objects and this is relatively simple when using a dependency container :

static void RegisterTypes()
{
 _container.RegisterType<IMainWindow, MockMainWindow>();
 _container.RegisterType<IChildWindow, MockChildWindow>();
 _container.RegisterType<IChildWindowNested, 
                                  MockChildWindowNested>();
}

And MockChildWindow having enough code to satisfy the contract of IChildWindow.

public class MockChildWindow : IChildWindow
{
 public object Owner { get; set; }
 public void Close()
 {
  //
 }

 public bool? ShowDialog()
 {
  return true;
 }

 public void SetOwner(object window)
 {
  Owner = window;
 }

 public bool? DialogResult
 {
  get;
  set;
 }
}

The viewmodel itself only uses methods exposed by the contract so we are safe to use a fake object as above for testing.

I have added a test app containing the custom popup and all code discussed here. Be sure to check it out!
Download sample application