Programming (back-end)

Handling DialogBox with WPF (MVVM)

imageHandling dialog windows in WPF using MVVM pattern is not such obvious thing as people may suspect. There are many discussions about it, and people come out with some solutions, that are more or less difficult, but still not perfect. I don’t like any and it made me describe my own.

 

 

 

Common solutions

As I have found, there is a couple of solutions for the problem. The most common ones are:

  • DialogService – creating a service used to handle all dialogs/windows in the application. Such a service can be used by any ViewModel. This way the view model knows that some other part of application must be shown/hidden as a dialog window. It’s somehow a design smell (link1, link2, etc.)
  • Dialog content injection – declare a markup of the dialog in XAML. Such a markup is then used to generate the new dialog window. Its visibility is controlled by a binding between ViewModel’s “Showing” property and the View. I thinks it’s better than the first one, but there’s too much logic behind the scene (link)
    Simplest approach

I think both solutions don’t answer my real need. I had a chat with an architect about this and we came to some simple conclusions:

  • MVVM is to create a good separation of presentation layer and the rest of the application, mainly by using bindings
  • Showing some UI parts as a dialog window or a panel, tab, accordion etc. is a presentation detail. It should be responsibility of the to control such a behaviour.
  • View doesn’t need to be stupid. WPF+MVVM developers got used to moving all the view code to bindings, but let’s not overuse it. If something is simpler to be done in code-behind, let it stay there.

In the end, I decided to invoke the famous “ShowDialog” method in the code-behind and pass the context (view model) to the newly created window. In the simplest case the view should not process the DialogResult, because this is the view model’s role. In my case the communication between the view model of the “Main window” and view model of the “dialog window” is based on events. Such a “Save” event exposed by the dialog’s view model can be used by “Main window” view model to add some item to a collection/repository but in the same time it can be used by the view of “dialog window” to close it.

 

Sample

The most beautiful words will never reflect the beauty of a sample, so here it is: Link

11 thoughts on “Handling DialogBox with WPF (MVVM)

  1. I think you’re exactly right here. The ViewModel is essentially marshaling data from the model to the view and vice versa. Its role is to let the view know when data is ready, and handle data changes initiated by the view. It should NOT be concerned with whether you’re asking for (for example) username/password in a dialog box, a plain form, a hidey/showy widget, or freakin’ carrier pigeon. Using a Dialog service IMO is binding to the view implementation.

    And also – and I’m ranting here because I’ve come from the Java/Spring and Ruby/Rails world like two weeks ago – Microsoft is pushing this MVVM when they haven’t even put the tooling in place to support it! Look at all these frameworks that spackle on handling event marshaling, requiring an aneurism to understand where the data is going and why, when using the code behind is so simple and easy – even if it does lead to tight coupling.

    I thought Spring was complex. This stuff is eating my lunch.

    1. John, I have to agree with you. I’ve been in development long enough (since VB 5) to know that since then development has gotten harder and not easier as it should have become. Too much “engineering” has gone into concepts that have already been solved long ago. I get why MVVM is desirable, but the level of complexity that it requires almost outweighs the complexity of just building the application using code behind. In all but the most complex applications, I can’t see the reason for thousands of lines of code put into viewmodels, commands and extremely complex properties only to end with slower apps that take much longer to understand. Microsoft should have invested in simpler boilerplate code and classes for building UI’s without inundating developers with countless interfaces to learn and binding expressions that look like line transmission noise. For business apps, I just don’t see the advantage.

  2. Thanks for sharing your idea. I downloaded the code and checked it out, easy enough to see what you’re saying. My only concern is how does this scale? If I have 50 popups in my largish app, are my only choices to add 50 “add event handlers” in the code behind, or 1 add event handler with a large switch.

    Regardless, I appreciate your time to provide input on the topic.

    1. Thanks Dan, actually it’s a very good question.
      Following this approach it’s far easier to unit test the ViewModel part, as it’s not affected by presentation details – there’s no DialogService nor any other fancy dependency. What else you don’t have to think if dialog window is shown or not.
      According to unit testing presentation logic – it remains pretty straightforward if using any test automation tools like MS TestRun.

  3. Every time you create a new CustomerEditorView passing the DataContext, your re-attaching the Save method to close the window. SO after adding 5 customers, it will call dialog Close 5 times!
    Rather a poor sample with such rookie mistakes.

  4. Hello Chris, I found your approach very interesting, but the sample download link doesen’t work anymore… Can you please provide a new one? Thanks!

  5. Hi,

    so this is actually what I’ve searched for and it took me like 2 weeks to find so thank you for that. The problem is I’m using a page that is opened inside a frame (which is inside a window) to open the dialog and in that case it says that there is a null reference when doing “var customerDialogBox =…”(just with my classes) in the OnAddClick method. Is it a problem because I’m using a Page inside a Frame instead of a normal window or is it just a problem with my code in generel because I can’t figure out what’s wrong with it?
    Do you have an idea maybe?

    Thanks

    Magnus

Leave a comment