I'm new to WPF and I tried to implement a demo application with RelayCommand.
My question is this:
If i want to execute a command which has to ask the user if he's sure he wants to execute it first - what's the best way to do it?
I need an "are you sure?" messagebox to pop. However, the command is executed on the viewmodel, and of course I don't want to mess with GUI there.
Thanks
The way I deal with this is to have an IDialogService interface that is registered in your IOC and available to your ViewModels.
The service then provides various ways of interacting with the "user". So you could have a ConfirmMessage method, that returns true or false based on the user accepting a dialog.
Then for unit testing say, you can have a different IDialogService implementation that allows you to feed canned responses to your ViewModel when under test.
I just ran into this myself. I'm using MVVM Light, and I used the Messenger to accomplish this.
I had my ViewModel send a GetConfirmationMessage, which I had registered in the code-behind. Within the handler for GetConfirmationMessage, I popped up the dialog box and got the reuslts. If the user clicked on OK, I then sent a ConfirmationReceived message, which was handled by the ViewModel to do the appropriate updates.
Related
I am using the MVVM pattern in my WPF application. In one of my Views I have a button that when clicked uses Commands to talk to its ViewModel. The problem I have is that I need the ViewModel to then talk to other ViewModels to call some of their public methods. I use IOC (Unity) and inject the container into the first ViewModel, so could access the others by using this. I’m not sure if this fits in with the MVVM concept.
Is it possible for all my ViewModels to somehow subscribe to the one button click?
Are any of these the recommended way of solving this problem or is there a better way?
To explain a bit more about my application, each view is a tab control with several textboxes. On the first tab there is also a button and combobox. The user is free to enter their own data or select an option from the combo. In this instance, if the button is then clicked I need all the tabs to load their textboxes based on the selected item in the combo from the first tab. I somehow need to wire this button click in such a way that the value from the combo is passed to all the related viewmodels.
You can use the EventAggregator. Have the command publish an event that the other ViewModels can subscribe to.
When the event is raised they'll all get the event, without needing for one VM to know the other VMs
Another option is to use Composite Commands instead of a regular command.
Make the command the button uses a composite command, and have the other viewmodels register to that Composite command.
You could go a few ways with this one:
use some kind of eventing framework to notify all subscribers if something happens: eg Prism EventAggregator. For this to work you'll need to set up Prism obviously. There are other (MVVM) frameworks out there which support some kind of event/message system like Caliburn.Micro or MVVMLight
Create a MasterViewModel that contains all the child viewmodels for all the tabs. This way the 'master' can subscribe to the PropertyChanged events from its children and execute the appropriate actions. Or the Master can even contain the commands which you are binding to.
I would recommend using some form of "Messenger" service. By this, I mean a class that implements the "Subscription Pattern."
I'm not sure which MVVM library you might be using, but if you look at the "MVVM Light Toolkit" - which is available on CodePlex - you will find a very light implementation of a Messenger there.
Basically each ViewModel will subscribe to receive a specific notification and your ViewModel with the combo box and button will publish the message when the button is clicked. It is really quite flexible in how you send the messages and your ViewModels don't need to know anything about each other.
If you are using the MVVM lite toolkit from GalaSoft you have access to the Messenger which would allow you to send a message that you can subscribe to in each of your view models.
// Send message from command handler
Messenger.Default.Send<MyMessage>(new MyMessage());
// Register for message in view models.
Messenger.Default.Register<MyMessage>(this, MyMessageReceived);
// Method to do work
private void MyMessageReceived(MyMessage myMessage)
{
// Do Work
}
I've a WPF application which allows me to edit some data.
I would like to make that if we try to close the application, the user must acknowledge that he will lost its modifications.
But here we are, I got several problem:
There is no "Closing" commands on the windows object(I can execute a command when I have an event from the code behind I guess)
I don't know how it's the recommended way to cancel something with the MVVM pattern? Normally I would have put the e.Cancel = true;, but we can't because it's a command
So how would you ask the user if he is sure to close the windows, with the MVVM pattern?
The concept is to add a behavior to your window that "hooks" into the window closing event. Once the behavior is hooked in, you can perform just about any action you need without violating the principles of MVVM. Check this link for information on how to create a window closing behavior:
http://gallery.expression.microsoft.com/WindowCloseBehavior/
Hope that helps.
Since you tagged this question as "mvvm-light", you can check the EventToCommand in MVVMLight. It may meet your needs.
This question is similar:
Handling the window closing event with WPF / MVVM Light Toolkit
I am building a WPF application and using the MVVM for the first time. Overall using MVVM has been very interesting and one of the major benefits is the nice separation between the view and the model classes. It kind of disciplines (at least young developers) to not to mix them together.
We have a scenario where a window needs to be closed on a button click after a confirm message box. Now this can achieved the old-way by handling the button click event and closing the window in the Window class itself. Or we can do it MVVM way by creating a command in ViewModel, call Window to show message box..etc.
I understand what needs to done here, but my question is - is it necessary to use MVVM commands in all cases? Are there exceptions where we should not use commands e.g. simple UI actions? Are we not overusing MVVM here? What exactly will the benefits doing everything the MVVM-way?
Or we can do it MVVM way by creating a command in ViewModel, call Window to show message box..etc.
Let me pick this apart, mainly because IMVHO I see this done wrong all the time - a lot of people try to do too much in the VM. First of all, ask yourself the question:
Is the prompt related to the data or business rules in any way whatsoever?
If it isn't, i.e. it is simply a "are you really sure?" type prompt, then this SHOULD be done purely within the code behind of the view. The only time the viewmodel needs to have any knowledge or take any action is when it actually has something to do with the viewmodel, in which case you should expose a command from the VM, but the actual window closing is still done from the code behind of the view.
The VM should know nothing about the view that it is bound to, that is one of the purposes of the MVVM pattern. It can expose commands, but it shouldn't know that a user has interacted with a specific UI element1, and it shouldn't directly know that the window is about to be closed. It is okay for the VM to prompt (via a dialog service, which you do have, yeah?) that the current data is unsaved, but it doesn't know about the window in general because it doesn't know how its data is presented.
Sometimes you will walk a fine line, and it is easy to over analyze whether something should be done purely from the view, purely from the VM, or as a mixture of both. If you remember the role of the VM, and remember that it is okay to have code behind in the view (provided it is only doing view related stuff and handing VM stuff off to the VM) then 99% of the time you won't have a problem.
1 For example, the VM shouldn't know or care whether the user just clicked a button, hyperlink, or touched a hot spot in an image. The same command can be used to handle any of this.
I have what, on the face of it, seems to be a really simple requirement - to be able to show a messagebox from within the view model of my WPF prism application.
Reading the documentation everything sounds good when I'm reading about Interaction Requests but I then find out that WPF doesn't support PopupChildWindowAction.
How are people getting around this. Basically I want a Messagebox in my shell module / or a infrastructure module that will subscribe to events and popup when that event is published.
Another issue I had was I want the popup to be centered on the parent window (the shell).
Just wondered how other people approached this. There seem to be a number of different ways to go but neither seem to fit the bill exactly.
From A CodePlex post by Karl Shifflet:
I've written a WPF version of the Interaction Request for my the Box MVVM Training here:
http://visualstudiogallery.msdn.microsoft.com/en-us/3ab5f02f-0c54-453c-b437-8e8d57eb9942
Install this Visual Studio Extension.
Create a new project with the MVVM Training Template.
Check out DialogInteractionRequestView.xaml and its implementation.
Cheers,
Karl
Use the RegionPopupBehavior from Prism 2.2 RI.
Use the EventAggregator in PRISM to subscribe to events, and have an in-memory presenter that listens for an event and then creates a view using the event data and calls ShowDialog on the view.
The dialog result can then be used to publish a 'response' event that would be routed back to the process that initiated the event that resulted in the display of the dialog.
Since PopupChildWindowAction is only in Silverlight, I have created my own PopupAction by inheriting from TriggerAction class and simply overridden body of Invoke() method to bring up a PopupWindow where I can pass any UserControl from xaml within the prism interaction trigger tag. From within ViewModel I am raising interactivity request event which triggers my PopupAction in view and opens the popup with desired user control being displayed onto it. Seems to work. I'll need to polish the example more. But here is a link -
http://wpfgrid.blogspot.com/2013/01/simple-prism-mvvm-way-to-display-dialog.html#step3
I'm building a WPF app and trying to conform to MVVM best practices. I'm using the MVVM Foundation framework and noticed the Messenger class, which I've read should be used for handling dialogs in WPF. This sounds great, but I'm totally not understanding how to use a Messenger for this purpose. Literally, all I want to do is open a modal About dialog --I don't need to pass any messages back and forth.
Was the intent of the Messenger class to be used for cases where dialogs require a message from its parent, or return a message to its parent? Is it overkill for an About dialog? Would I be better off simply adding code to an event handler to show the dialog?
The idea behind the messaging pattern doesn't specifically have anything to do with showing dialogs. The idea is simply to provide a decoupled way to communicate between ViewModels.
You can leverage this infrastructure to solve your problem but you will have to implement the showing of the dialog yourself.
As Phillip showed above you can send messages between ViewModels. When your ViewModel receives the message it can set it's own internal property, say "ShowDialog", to true.
You can then have a binding that reacts to this property change operation and opens a dialog.
I have also built a simple messaging framework for the MVVM pattern that borrows from Josh's idea (and several other existing frameworks) you can read about it here
Say you have a parent view and a dialog view. In MVVM they would both have a view model. It is good to keep these view models decoupled, i.e. they don't have references to each other. And yet they need to communicate to each other. The Messenger class acts as a go between or Mediator to mediate the communication of information between the two classes. See the code taken from Josh's blog.
Here is Object A. It's call to the mediator's Register method implements: when I receive the message ObjectBSaidSomething, from the mediator, I'll cache it in the member WhatObjectBSays.
Here is Object B, which implements: I'm going to send a message ObjectBSaidSomething. Note, that Object B knows nothing about Object A. There might be nothing listening for ObjectBSaidSomething, or 100 objects listening for ObjectBSaidSomething, but Object B doesn't know and doesn't care. This is good decoupling, and this is why the Mediator pattern is a good idea. And this is the way the MVVM foundation is recommending that information is passed between view models.