0
votes

This question refers to a WPF application based on PRISM 5.0 and the MVVM pattern.

Sometimes when users make decisions, that could have unwanted or negative consequences, it is very common to ask the user, if he really wants to go on and proceed.

For example: One common way, is to ask the user with a messagebox, if he really wants to delete data, that can not be restored after deletion.

The problem is: If I call the MessageBox inside the ViewModel, the ViewModel becomes untestable from the outside.

//BAD!
public class ViewModel
{
    public Boolean Delete()
    {
        //Blocking and therefore untestable in automatic UnitTests
        MsgBoxResult result = MsgBox.Show("Do you really want to delete?"); 

        if (result == yes) {//Do stuff that deletes data here;}

    }
}

One possibility would be, to ask the question in a different private method, that calls the public method

//BETTER, BUT OK?
public class ViewModel
{
    private void OnDeleteAction
    {
        MsgBoxResult result = MsgBox.Show("Do you really want to delete?"); 
        if (result == yes) {Delete();}
    }

    public Boolean Delete()
    {
        //Testable from the outside again, because no blocking question

        //Do stuff that deletes data here
    }

My question: Is is this a good way or is there a more elegant way to ask the user inside a ViewModel? Can you give me a hint or link, what is the best for PRISM 5.0?

I know, that a rule of thumb is, not to use any UI elements in the ViewModel, but I see no alternative to a blocking MessageBox or something else, that blocks the process, before proceeding.

Thank you any hints!

2
As per my understanding one should not write any view related code in view model and logic related code in view side. So you can open the message box in view code behind and based on the user choice you called your delete method in the view model class.Kiran Paul
public interface MuhMessageBox { bool AreYouCrazy(string message); }user1228

2 Answers

3
votes

There are two alternatives that I know of which can reduce coupling between View and ViewModel: using an interaction service, and firing interaction requests. Both are explained very well here; you might want to take a look.

The general idea is that you abstract how asynchronous interactions are done and work with something more similar to event-based logic while at the same time allowing the ViewModel to express that it wants to interact with the user as part of an operation; the net result is that you can document this interaction and unit test it.

1
votes

Prism Interactivity is the way to go here. This allows you to do Confirmations, Notifications, and create custom dialogs that work well with the MVVM pattern. I use them successfully in my Prism applications.

Here are some links to some code in the Prism repo on GitHub:

Notification Request

Confirmation Request

Custom Content

Custom Request