0

I need to send notification from ViewModel to View in MVVM WPF application. In most cases it will be simple MessageBox on View side. Is it unacceptable violation of MVVM pattern to use types like System.Windows.MessageBoxResult or System.Windows.MessageBoxImage in ViewModel (in this case VM must reference UI-specific libraries)?

I need to pass title, message and notification type from VM and by creating custom enumerations I am in fact copying existing functionality from .NET Framework.

Ondřej
  • 1,645
  • 1
  • 18
  • 29
  • "Is it unacceptable violation of MVVM pattern to use types like System.Windows.MessageBoxResult or System.Windows.MessageBoxImage?" This only depends on how you intend to reuse your view model. By using these types, reuse is limited to WPF applications. Otherwise there isn't anything wrong with it. But there are of course people with a different *opinion*. – Clemens Nov 01 '16 at 08:23
  • I think that ViewModel should be 100% separated from purely View's stuff like these MessageBox enums, no matter what kind of application it is. – Ondřej Nov 01 '16 at 08:30
  • http://stackoverflow.com/questions/3801681/good-or-bad-practice-for-dialogs-in-wpf-with-mvvm – blindmeis Nov 01 '16 at 08:32
  • 2
    Then why are you asking this question? – Clemens Nov 01 '16 at 08:32
  • Guess why. To confirm my theory with someone with better experience in this matter. – Ondřej Nov 01 '16 at 08:35
  • 1
    You theory is just an opinion, and therefore off-topic on StackOverflow. – Clemens Nov 01 '16 at 08:49
  • @Clemens My question is less off-topic then your arrogant comments and can be useful for others who meet same problem. – Ondřej Nov 02 '16 at 07:25
  • My comment is all but arrogant. You have an opinion, now you're trying to find someone that confirms or shares your opinion. When someone else says that they have a different opinion, you don't want to here it. So why ask the question at all? – Clemens Nov 02 '16 at 08:10
  • @Clemens Where did you get that if someone else have different opinion, I dont want to hear it? I am just explaining my point of view. – Ondřej Nov 02 '16 at 08:47
  • Re-read my first comment and your response to it. – Clemens Nov 02 '16 at 08:53
  • @Clemens By writing "there are of course people with a different opinion" vs. "You theory is just an opinion, and therefore off-topic" you declared your comment as off-topic, because it is just another opinion. Now it is right time to end this useless conversation. – Ondřej Nov 02 '16 at 09:48
  • Then why don't you just stop discussing? FYI, a comment may be inappropriate but it can't be off-topic. What can be off-topic is a question. Please go back to the Help Center and read [What types of questions should I avoid asking?](http://stackoverflow.com/help/dont-ask). – Clemens Nov 02 '16 at 09:55
  • @Clements is right. Stackoverflow question should sound like "How to do this or this?", or "I got this error. What did I wrong?". Stackoverflow is not place to discuss opinions and that's what differentiate it from other Q/A sites, like Quora for example. – Liero Nov 02 '16 at 15:41

3 Answers3

1

You don't need notification mechanism. That's one option. Another is using simple service class:

public class ViewModel
{
    IDialogService _dialogService; //ctor injection or use service locator

    public void CommandExecute()
    {
        _dialogService.ShowMessageBox(...);
    }
}

public interface IDialogService
{
    bool? ShowMessageBox(params....);
}

public class DialogService : IDialogService
{
    public bool? ShowDialog(params...)
    {
        MessageBox.Show(params...);
    }
}

I find this approach more straightforward, easier to understand and easier to debug. Messaging may easily turn into memory leak and in this case I don't see any benefit over my approach.

EDIT:

Will you use custom enum in ShowMessageBox parameters, or will you use System.Windows.MessageBoxImage?

First of all, ViewModels belong to presentation layer. It is OK to use enums like System.Windows.MessageBoxImage in ViewModel. In MVVM, ViewModels are separated from Views because of following reasons:

  • ViewModels expose data and logic from Model in such way that is easily consumable from Views (e.g DataBinding)
  • ViewModels are easier testable
  • ViewModels provides better design time support (Blendability, test data)
  • ViewModels separates application logic from the actual presentation markup which makes it easier to understand (readbility)

Does using enum like System.Windows.MessageBoxImage breaks any of the points above? The answer is no.

If you wanted to reuse IDialogService and your ViewModels on multiple platforms, for example WPF, UWP and Xamarin, then you need to create your own enum, because it may not exist on all platforms. The golden rule is: don't add another layer of abstraction if you don't need it.

Liero
  • 25,216
  • 29
  • 151
  • 297
  • Thanks. I am well aware of all options that I have for displaying something from VM. But my problem was that I was not sure about if it is correct to use UI (View) types in VM. Look at your IDialogService.ShowMessageBox. What parameters will be there? You need to display either information, or warning. Will you use custom enum in ShowMessageBox parameters, or will you use System.Windows.MessageBoxImage? If you will use MessageBoxImage, you will need to reference System.Windows UI library in every place (project) where IDialogService.ShowMessageBox is used. – Ondřej Nov 02 '16 at 12:10
0

You could have the view implement an interface, say INotificationService and then pass the view to the view model constructor. That won't violate MVVM, and you will still be able to bind the view model to the view using the DataContext property on the view.

Timothy Ghanem
  • 1,606
  • 11
  • 20
  • I am doing these notifications by raising event in ViewModel and catching it in View. Method is bound to VM's event in View's DataContextChanged event. – Ondřej Nov 01 '16 at 08:33
  • In your way the view has to know that there's an event in the view model that it should listen to. While the way i described to you will make it more explicit in terms of separation of concerns as neither the view nor the VM know anything about the other; the view doesn't have to know anything about the view model nor the view model has to know anything about the INotificationService dependency except that it implements some method called Notify or whatever. – Timothy Ghanem Nov 01 '16 at 08:40
  • I read a lot about MVVM and it is perfectly OK if View knows about ViewModel. Only ViewModel does not know about View and Model does not know about ViewModel. Anyway, I need to deny/confirm using pure UI enums in ViewModel. – Ondřej Nov 01 '16 at 09:25
  • 1
    @TimothyGhanem a view can very well know about the viewmodel. But you are right that required dialogs should be requested with an explicit interface. I would only use the event approach for some optional one way information, where the view is free to decide whether its worth displaying. – grek40 Nov 01 '16 at 10:07
  • @grek40 I am using this approach two way. For example ViewModel needs confirmation of something, so it raises event. It does not matter what will respond to this event, ViewModel gets value from customized EventArgs after raising and does something based on this. I cant imagine how to do the same using some interface, it only complicates things and brings no advantages over my solution. – Ondřej Nov 01 '16 at 10:55
  • @Ondřej If the confirmation is required, you need to define what happens if your event was not handled - the viewmodel shouldn't assume things about the views behavior. Regarding the interface approach: you define an interface within the viewmodel, with methods like `bool? ShowConfirmation(string text)` and if you feel like it, implement a static assessible property of that type. In the view, create a class that implements the interface. In the application startup code, create an instance of the class and hand it over to the viewmodel, where it can be used when needed. – grek40 Nov 01 '16 at 11:45
  • @grek40 If event is not handled, there is default value in custom EventArgs's Result property, which is Nothing (null) for Boolean? (bool?). Your solution makes things unnecessarily complicated. I just fire event and on the next line check returned value. If that value was set by UI, unit test, or anything else does not matter. – Ondřej Nov 01 '16 at 12:24
  • @Ondřej I can't let the 'complicated' claim stay uncommented. The interface thing is defined once for the project, it can be used as a code-oneliner and it can be re-implemented by unit tests or whatever. Your solution requires event handlers for every viewmodel-showing-view, which means *some* extra work for every view in the project. – grek40 Nov 01 '16 at 12:36
  • @grek40 And when you will have the need for notification other way than MessageBox (for example some custom UI in View), you are doomed with your solution. Anyway, my original question was if it is correct to use view-specific things in ViewModel, in this case MessageBox enums from System.Windows. – Ondřej Nov 01 '16 at 13:15
-2

I decided to keep ViewModel as clean of UI (View) stuff as possible, so I will create custom enumeration inspired by MessageBox and tailored exactly to my needs.

Ondřej
  • 1,645
  • 1
  • 18
  • 29
  • This doesn't belong here as an answer, but should be a comment instead. And it certainly should not be the accepted answer. If your best solution was derived from Liero's answer, you should accept it instead. Give credit where credit is due. – s3c Aug 25 '21 at 07:02