WPF DataGridRow Double Click With MVVM

On my current project, we need to open a record for editing when the DataGridRow is double clicked. Unfortunately, the WPF DataGrid doesn’t support this functionality out of the box. There are, however, a couple ways to make this happen.

One way is to handle MouseDoubleClick event on the DataGrid. We are using Caliburn.Micro, so it is easy to get the MouseDoubleClick event to route to our view model. The view model can then assume that the selected item is to be edited. The problem with this is that double clicking anywhere on the DataGrid will trigger this event, including the scrollbars. That means that quickly scrolling down the items could trigger a double click and cause whatever item was last selected to be edited, which is unacceptable.

What we needed was to somehow handle the MouseDoubleClick event on each DataGridRow, make sure the one being double clicked on is actually selected, then call tell the view model to edit it.

I ultimately came up with two solutions. One uses a little code-behind and applies only to one case at a time. The other uses an attached DependencyProperty and is general enough to apply to all cases.

Using Code-behind

The code-behind solution may break the MVVM pattern, depending on your point of view. I feel that using code-behind makes sense in cases where you have logic that is specific to your how your view represents the UI.

First, you need to create the MouseDoubleClick event handler in the code-behind.

Next, you need the wire up each DataGridRow to use that handler for MouseDoubleClick events. You can do that with styling.

That’s it. This solution is pretty straight-forward. However, there are two problems with the code-behind solution.

The first problem is that this solution doesn’t scale. What I mean by that is that you have to re-implement it every time you want to use it.

The second problem is that it uses code-behind. As I said earlier, I believe the use of code-behind has its place. However, I prefer to stay away from it if I can.

Using Attached DependencyProperty

The attached DependencyProperty solution uses a helper class so that it can be reused across your application. It also assumes that your DataGrid’s DataContext is your view model. If that is not the case, you will need to modify it.

This helper class ties into the DataGrid’s LoadingRow event and uses reflection to find a specified method on the DataContext and execute it. All you have left to do is use it.

All you need to do is provide the name of the method on your view model to execute when the double click has occurred and the rest is taken care of.

Conclusion

While it’s unfortunate that WPF doesn’t provide this functionality right out of the box, it is not difficult to implement it yourself. Silverlight suffers from this same shortcoming. This solution won’t work as-is for Silverlight. It would need to be refactored into using Behaviors instead of an attached DependencyProperty.

I have posted a complete solution on github: https://github.com/brentedwards/DataGridRow_DoubleClick

Happy coding!

Share

An Implicit DataTemplate Alternative for Silverlight 4

A few weeks back, I had the opportunity to write a guest post for my employer, Magenic. The post is about a solution I came up with for an implicit DataTemplate alternative with Silverlight 4. Enjoy!

Share

Getting Dirty with Windows Phone 7 Presentation Materials

If you attended my presentation, Getting Dirty with Windows Phone 7, I hope you found it useful.  If you would like to play with the sample application I used in my demo, I have made it available on github: https://github.com/brentedwards/GettingDirtyWithWP7.  I didn’t feel the need to post my slide deck.  However, here are the valuable links I had listed:

http://create.msdn.com/
Tools, Quick Starts, Tutorials

http://silverlight.codeplex.com/
Silverlight for Windows Phone Toolkit

http://www.jeff.wilcox.name/2010/05/sl3-utf-bits/
Silverlight Unit Test Framework for WP7

http://www.scottlogic.co.uk/blog/colin/2010/05/silverlight-multibinding-solution-for-silverlight-4/
Silverlight Multibinding

http://mvvmfabric.com
MVVM Fabric

If you attended my session, please take a moment to rate my presentation.

Fox Valley Day of .NET – March 5, 2011

St. Cloud .NET User Group – March 9, 2011

Twin Cities Code Camp 10 – April 9, 2011

Twin Cities Code Camp 11 – October 9, 2011

Share

Getting Dirty with Android – Presentation Materials

If you attended my presentation, Getting Dirty with Android, I hope you were able to learn a thing or two.  If you want to review what I covered or play with the sample application that I worked with during the demos, I have made both available.

Slide Deck: http://www.slideshare.net/brentledwards/getting-dirty-with-android
Sample Application: http://github.com/brentedwards/GettingDirty

If you attended my session, I would appreciate if you took a few moments to review it.

Twin Cities Developers Group, Feb 8th 2011

Chippewa Valley Code Camp, Nov 13th 2010

Iowa Code Camp, Nov 6th 2010:

Share

WPF with MVVM: From the Trenches on dnrTV!

A few weeks ago, after presenting at CodeMastery, I sat down with Carl Franklin from dnrTV! to discuss WPF with MVVM.  The discussion is centered around the demo portion of my presentation entitled WPF with MVVM: From the Trenches.  This presentation is the precursor to the work I have done with MVVM Fabric.  Without further ado, check it out here: http://dnrtv.com/default.aspx?ShowID=184 – complete with an un-flattering pic Winking smile

Share

MVVM Fabric: Using a View Placer

A while back, I wrote about the navigation solution provided by MVVM Fabric.  I also wrote about using the ModalViewPlacer provided by MVVM Fabric.  In this post, I will talk about how to provide your own implementation of the IViewPlacer interface.

Overview

Since each application is unique, with its own unique UI, MVVM Fabric leaves it up to you, the developer, to provide the mechanism to place a view into that unique UI.  IVewPlacer is that mechanism.

An implementation of the IViewPlacer interface is required by the navigation solution provided by MVVM Fabric.  It will be used by the ViewController to place a view into your application when a request is made to navigate to a view.

A First Look

The IViewPlacer interface provided by MVVM Fabric follows the single responsibility principle.  Its only job is to place a view into your application, which you can see by looking at the interface itself.

When you implement IViewPlacer, you must provide an implementation for the PlaceView method.  The PlaceView method takes a ViewResult as a parameter.  So, let’s look at the ViewResult class as well.

As you can see, the ViewResult class has two properties.  The first property is the actual instance of the view, as created by the view factory.  This view will have a fully loaded view model and is all ready to make an entrance into your UI.  The second property is the ViewTargets value for that view.  There may be times where you need to place certain views in different places than the rest of the views.  With the ViewTargets property on ViewResult, you know what view you are placing and can act accordingly.

IViewPlacer Implementation

The sample application provided with the MVVM Fabric source has an implementation of the IViewPlacer interface.  We will be looking at a simplified version of that implementation.

The sample application has a tabbed user interface, so the view placer needs to take a view and place it into the TabControl used by the main view.  As you can see, it cycles through any existing views so that duplicates are not shown.  Then, if the view is not a duplicate, it is placed into the TabControl and given focus.

This is a simple UI, so a fairly simple view placer is needed.  More complicated UIs will likely need more complicated view placers.  As an example, a previous project I worked on used a docking solution similar to Visual Studio.  In that case, the view placer would need to be aware of what views go into what docking sections.

Conclusion

The IViewPlacer interface is integral to the navigation solution provided by MVVM Fabric.  Since each application’s user interface is different, it is left up to the consumer of the library to implement this interface.  The complexity of the view placer implementation is dependent on the complexity of the user interface, but placing the view is its only responsibility.

Share

MVVM Fabric: Using a View Authorizer

A while back, I wrote about the navigation solution provided by MVVM Fabric.  In that post, I mentioned the interface IViewAuthorizer.  In this post, I will describe that interface and when to use it.

Overview

An IViewAuthorizer implementation is an optional parameter to the ViewController which, when provided, gives your application an opportunity to determine if a user is authorized to see a requested view prior to the view being shown.  If you do not provide an IViewAuthorizer implementation to the ViewController, the ViewController assumes that the user is authorized to see every view that is requested.

A First Look

First of all, let’s take a look at what the IViewAuthorizer interface looks like.

Pretty simple, really.  IViewAuthorizer has only one responsibility, to authorize views.  The AuthorizeView method takes a ViewTargets value as a parameter so it knows which view to authorize and returns a ViewAuthorizations enumeration value.  The ViewAuthorizations enum looks like the following.

The first option, Authorized, is self-explanatory.  If the view authorizer determines that the view is authorized, the ViewController will show the view.

The second option, NotAuthorized, is self-explanatory as well.  If the view authorizer determines that the view is NOT authorized, the ViewController will not show the view.  However, the ViewController will also throw an InvalidOperationException if the user is not authorized for a view.

The third option is for those more ambiguous situations where the view may be authorized, but it really shouldn’t be shown, yet you don’t want to throw an exception.  Let me give an example from my last project to help illustrate a situation where this is useful.

A DoNotDisplay Scenario

With my last project, there were views that depended on data provided by other views.  The other views had to be presented to the user so they could provide the data.  So, we had a situation where some views were prerequisites for other views.  Using the navigation solution provided by MVVM Fabric, it was easy to consolidate all the prerequisite checks in one place using an IViewAuthorizer implementation.

I developed a helper class that allowed me to specify which views were dependent on information from other views.  When the AuthorizeView method was called, the view authorizer would check to see if there were any prerequisites and, if there were, check to see if they were satisfied.  If they were not satisfied, the view authorizer would then request to show the view that will satisfy the prerequisite.  All that happens BEFORE the view that was originally requested was shown.  So, if the user cancels out of the prerequisite view before the prerequisite was satisfied, I did not want the originally requested view to be shown, but I also did not want the ViewController to throw an exception because the user opted to cancel the process before it could be completed.  So, I had the view authorizer return DoNotDisplay in that situation where the prerequisite was not met due to a user operation.

Conclusion

IViewAuthorizer provides you the opportunity to check whether a user is authorized for a view prior to showing the view.  It also provides you the ability to let the user gain the authorization to see the view prior to showing the view.  However, IViewAuthorizer is completely optional.  So, if your application has no need to prevent users from seeing any view, you do not need to provide an implementation for IViewAuthorizer.

Share

MVVM Fabric: Using TriggerAction

A few days ago, I wrote about using MVVM Fabric’s ActionCommand.  Commanding can be useful with controls that provide a Command property, such as Buttons and MenuItems.  However, commanding doesn’t help when you want to wire up arbitrary events to your view model.  That is where TriggerAction come in.

Overview

TriggerAction is a look-less framework element that wires itself up to whatever event you specify on whatever control you specify.  When that event is raised, TriggerAction calls whatever method you specify on your view model.

TriggerAction was written by Rocky Lhotka for his business object framework, CSLA .NET.  Since CSLA is open source, Rocky gave me permission to include TriggerAction with MVVM Fabric because of the great value it would provide consumers of the library.  I have been using a precursor of TriggerAction, called InvokeMethod, on my projects with great success.  While InvokeMethod has some limitations (no designer support and the ability to only wire one event for a control), TriggerAction provides a more robust implementation and eliminates these issues.

Wiring an event to a method

There’s really two different ways that I typically use TriggerAction.  The first way is when I really only care if an event happened.

For this example, we will wire up TriggerAction to call the Close method on our view model when a button is clicked.  We first need to name the button that we will be hooking events from.

Next we place the TriggerAction on our view.

Notice that I used an Element Binding for the TargetControl property.  That is how we tell TriggerAction to listen for the click event on our button.  I also set the MethodName property with the name of the method we want called.  It is important to note that TriggerAction looks for the method specified on its DataContext.  So, you have to make sure that the DataContext is your view model if you want it to call methods on your view model.

Now we need to write the Close method on our view model.

We’re all set.  When the Click event is raised on our button, TriggerAction will look for a method called Close on its DataContext (which is our view model).  The method it looks for must have 0 or 2 arguments.  We have the 0 argument version here because we only care that the event happened.

Wiring an event to a method with a MethodParameter

The second way I typically use TriggerAction is for those situations where I need to pass a parameter to my method when the event I care about is raised.

For this example (and the one you will see in the sample application), we will wire up the MouseDoubleClick event on a ListView to pass the SelectedItem back to our method on the view model.

First, the ListView.

 

Next, the TriggerAction.

 

There are two things different about our usage of TriggerAction here.  The first difference is the addition of the MethodParameter property, which we are binding to the SelectedItem property on the MoviesList element.  The second is setting RebindParameterDynamically to true.

The MethodParameter property on TriggerAction is where you bind whatever you want from the view to be passed back your view model.  This can be something on the element you are listening for events on or something somewhere else on the view.

The RebindParameterDynamically property is really cool.  When this is set to true, TriggerAction will go out and rebind to the method parameter before calling back to your method so that you are always sending back the latest and greatest.  Since not all of the properties you want to bind to raise property changed events, this is a huge benefit.

Now, on to the view model.  As I mentioned before, when looking for methods on our view model, TriggerAction will look for methods with either 0 or 2 parameters.  Since we need that MethodParameter passed in, we will need the 2 parameter version.

 

This is a typical event handler method signature.  The event args that are passed through are ExecuteEventArgs, which have some useful properties.  The property we care about right now is the MethodParameter property, which needs to be cast before we use it because it is of type Object.  Once we cast it as our Movie business object, the view model is free to do what it needs with it.

Conclusion

Although commanding is a decent start to executing methods on your view model, TriggerAction is a much more robust solution.  With drag-and-drop designer support, the ability to bind a method parameter and the ability to have that method parameter dynamically updated at execution time, TriggerAction is an extremely powerful way to wire arbitrary events from your view to your view model.

Share

MVVM Fabric: Using ModalViewPlacer

In yesterday’s post, I talked about how to do testable navigation with MVVM Fabric.  In that post I made mention of ModalViewPlacer as a stock implementation for IViewPlacer provided by MVVM Fabric.  I think ModalViewPlacer is worth explaining so that you can make effective use of it.

Overview

ModalViewPlacer is an implementation for IViewPlacer which displays views as a modal dialog.  It works with two interfaces provided by MVVM Fabric: IModalView and IModalViewModel.

IModalView must be implemented by the view and provides some hooks for ModalViewPlacer to do its thing.  MVVM Fabric provides an implementation of IModalView, called ModalView, to simplify things.  ModalView inherits from Window.  I will show how to use this shortly.

IModalViewModel must be implemented by the view model and provides a hook for view models to request that they be closed.  MVVM Fabric also provides an implementation of IModalViewModel, called ModalViewModelBase.  ModalViewModelBase inherits from ViewModelBase and provides implementations for the hooks.

When a modal view is shown, its view model needs a way to be able to request the view be closed.  IModalViewModel provides an event, RequestClose, which can be raised.  The view subscribes to that event and closes itself when the event is raised.  ModalViewModel provides several methods which can be used to initiate that close request.  The methods also provide the ability for the view model to indicate whether it was accepted (or cancelled) and give back some sort of result object.  ModalView then takes what was provided by the view model and exposes them as properties to be used by ModalViewPlacer.  ModalViewPlacer will use those properties to create a new message, called ModalViewClosedMessage, and publish it to the message bus to signal to the application that the view was closed.

Using ModalViewPlacer

The sample application provided with MVVM Fabric uses ModalViewPlacer in conjunction with its own custom implementation of IViewPlacer to have a combination of tabbed views and modal views.  This example will be more simple and will only leverage ModalViewPlacer.

First off, you need to have your view inherit from ModalView.

Next, you need to update your XAML to reflect this.

Notice that Window is replaced by nav:ModalView, with nav being the namespace I defined for MVVM Fabric.

Next you need to have your view model inherit from ModalViewModelBase.

Your view and view model are all set now.  You can have methods on your view model such as Accept and Cancel to react to the OK and Cancel buttons.

This illustrates two uses of the NotifyCloseRequest method provided by ModalViewModelBase.  The Accept method signals that the view was accepted and returns Keywords as a result.  Cancel signals that the view was not accepted (read cancelled).

To wire up and request a modal view is no different than I described in yesterday’s post. unless you care about the modal view being closed and possibly the results it provided.  If that is the case, then you must subscribe to the ModalViewClosedMessage from the message bus prior to making the request for the view.

With the ModalViewClosedMessage, you can determine which view just closed and act according to whether the view was accepted and optionally use the result.

Conclusion

Modal dialogs are a type of view that you don’t want to overuse in modern applications, but there usually is a need for at least a few of them.  Using the ModalViewPlacer, you can tap into the navigation functionality provided by MVVM Fabric and still show modal dialogs in a testable way.

Share

Testable Navigation with MVVM Fabric

One of the biggest problems I encountered while writing WPF apps with MVVM is navigation.  The traditional approach to navigation would be to have one view create the view being navigated to.  Now, there’s a couple of issues with that approach which make it less than desirable.  The first issue is that having one view create another view heavily couples the two views.  The second issue is that this approach quickly becomes very difficult (if not impossible) to unit test.

Things get more complicated when view models are introduced.  Since the functionality that initiates the navigation is going to be in the view model, that would mean the view model would have to know about the new view.  When I structure an MVVM solution for WPF, I create a separate class library for the view models.  The client project (which contains the views) needs to have a reference to the view models project in order to use them.  That means there would be a circular dependency if the view model project had a reference to the view project as well.  Doing the traditional approach with this project structure is no longer even an option.

MVVM Fabric solves the navigation problem with some convention, some configuration, a pinch of dependency injection and a dash of the message bus.

10,000 ft View

MVVM Fabric funnels all navigation through one source, the ViewController.  The ViewController subscribes to the message bus to listen for ShowViewMessages requesting views.  When a view request comes through, the ViewController coordinates the resolution and creation of the view and its view model.  Then the ViewController takes the new view and passes it along to the view placer to be placed in the application.

By leaning on the message bus to request a view, writing unit tests for the view model making the request becomes a breeze.  By letting all navigation flow through the ViewController, it de-clutters your codebase by eliminating the need for code creating views throughout the application.  This decoupling will greatly simplify your application and each view model can focus on its own responsibilities and not have to worry about the specifics of any other view or view model.

Convention

As I mentioned, there is an element of convention required to leverage the navigation model provided by MVVM Fabric.  The conventions are as follows:

  1. All view models must have a default constructor.
  2. View models have the option of providing a Load method as a way of allowing itself to be loaded during the dynamic creation process provided by MVVM Fabric.  The Load method may take 0 or 1 arguments.
    1. If there is an argument, it can be whatever is required by the view model to load itself.
    2. If more than one thing is required to load the view model, I recommend creating some sort of criteria class that contains any required data.
  3. A class inheriting from ViewTargets must be provided with unique definitions for all navigable views in the application.

The reason that all view models must have a default constructor is that they are dynamically instantiated when a view is loaded.  Since there are many scenarios where a view model will need some information to load itself (picture a detail view, for example), MVVM Fabric looks for a public Load method on the view model and calls it if found.  That Load method may be a no argument method which simply kick-starts the loading needed for the view model or it may take a single parameter.  If the Load method takes a parameter, a parameter must be provided when the view is requested.  That’s where the ShowViewMessage comes into play.

The ShowViewMessage has a ViewTargets parameter (which tells the ViewController which view is being requested) and an optional parameter called LoadArgs.  LoadArgs can be anything required by the view model, but if something is provided a Load method which takes that object type as a parameter must exist on the view model or an exception will be thrown.

If you saw my presentation WPF with MVVM: From the Trenches, you heard me talking about how ViewTargets is an enumeration.  While refactoring my navigation code into a stand-alone library for MVVM Fabric, one of the issues I had to overcome is the fact that enumerations cannot be inherited from and extended from an external object.  The reason I liked using an enumeration to articulate all the navigable views in the first place is because it provided a level of safety at compile time when views are requested.  I could have used strings instead to identify views, but that would not make refactoring easy.  To overcome this limitation of enums, I leveraged a concept introduced by Hugh Ang to create an Enumeration class which acts like an enum, but can be extended.  It’s not a perfect solution, but it does help address the compile-time and refactoring issues.  The new ViewTargets inherits from this Enumeration class and must be further inherited from in your implementation.

Configuration

In order to leverage the navigation model provided by MVVM Fabric, you must provide implementations to an interface or two: IViewPlacer and optionally IViewAuthorizer.

IViewPlacer is what will actually place the views when the navigation model has loaded the view and it’s view model.  I leave that implementation up to you because each application is different in how views are presented.  The sample application provides an implementation that works with the tabbed interface used by Movies.  MVVM Fabric does contain an implementation of IViewPlacer for views displayed as modal dialogs because this will likely be the same across applications.  The sample application shows the usage of ModalViewPlacer in conjunction with it’s custom IViewPlacer to illustrate how you could implement a combination of the two.

IViewAuthorizer is an interface which can optionally be implemented to give you control over whether the user is authorized to see each view before it is shown.  This allows you to put restrictions on your views from one location.

Enough talk, time for code!

Here’s the part you are probably waiting for, how do I make it work?  Here are the steps that you need to take to get up and running.

1.  Inherit from ViewTargets and provide values for your views.

2.   Provide an implementation for IViewPlacer (unless you strictly use ModalViewPlacer)

Note: Your custom ViewPlacer would also be a good place to subscribe to CloseViewMessages from the message bus.  Since views have the ability to request that they be closed, it only makes sense to keep the showing and closing functionality in the same place.  You can see this in action with the sample application.

3.  Provide a way to wire up the IViewConfigurationResolver when the application starts up.

Note: The sample application calls ContainerConfiguration.InitContainer() in the application’s OnStartup method.  I also do some configuration for Windsor Container in this method.

4 (Optional).  Provide an implementation for IViewAuthorizer.  This one is up to you since application security varies on a case-by-case basis.

5.  Instantiate the ViewController and all the pieces it needs.  This will probably be done in the code-behind of your main window.  The sample application uses Castle Windsor, so I will leave it up to you how you get all the pieces standing.

You’re There!

The steps described above may seem like a lot of work, but the work is almost all front-loaded.  When a new view is added, only steps 1 and 3 must be revised to accommodate the new view.

Now, let’s look at how to initiate navigation.

That’s it!  This example shows how to pass a parameter to the Detail view.  You could remove the LoadArgs parameter from the ShowViewMessage for those cases where there is either no need for a Load method on the view model or the Load method has no parameters.

From a testing perspective, the above example is extremely simple to write unit tests for.  You would simply assert that the message bus received a ShowViewMessage with the correct arguments.

Conclusion

The navigation model provided by MVVM Fabric takes a pain point with the MVVM pattern and smooths it over in a testable manner.  With all the navigation being handled in one place, it reduces the surface area that you must test for in your application.  A testable application is a maintainable application!

Share