1

I have been strugglin whit this problem for quite some time now. I'm building my first WPF MVVM application. In this App i have a AppView (with it's corresponding viewmodel). Child views are contained into tabs and represented by separated views (UserControl) and have one viewmodel for each view. So far so good.

In one view, a have a list of costumers, and a Delete button. I also have a correspondig command on the viewmodel to actualy delete the record, and this work fine. Now I want the delete button to create a new view with two buttons, one for confirmation and the other for cancel, and then if user click the "Confirm" button execute the delete.

The problem here is that each view, and its correspondig viewmodel are isolated from the other (as long as I understand) so i cannot access the second view viewmodel to see if the confirm button is clicked.

The only posible solution that i found so far is to add an event on one view and subscribe the other view to that event. But this technic is quite complex for such a trivial task. Is there other alternatives? Can't the two views share the same datacontext or viewmodel?

Thanks!

ericpap
  • 2,917
  • 5
  • 33
  • 52
  • The new view should be *modal,* and should be called from a function which will *return a value* to the original view. A [dialog box](https://msdn.microsoft.com/en-us/library/aa969773(v=vs.110).aspx) is the simplest way. – Robert Harvey Apr 11 '15 at 18:51
  • Thanks @RobertHarvey. Yes my Idea is that the second view is Modal to the first view. That part i have already resolved. But my second view is a separeted XAML, with it's corresponding viewmodel. So how do I "talk back" from view 2 viewmodel to view 1 viewmodel? – ericpap Apr 11 '15 at 18:57
  • There's a pretty good example [here](http://blog.magnusmontin.net/2013/04/20/implement-a-confirmation-dialog-in-wpf-with-mvvm-and-prism/). – Robert Harvey Apr 11 '15 at 19:04
  • View models communicate best with a messaging framework such as the one provided by mvvm light. It might seem a little overly engineered at first but since you're starting out, worth knowing and looking into. Here is a similar question I answered with an example... http://stackoverflow.com/questions/25158972/how-to-establish-communication-pass-data-between-two-viewmodels/25159514#25159514 – kidshaw Apr 11 '15 at 19:08
  • Ok. I'm using Caliburn.Micro here, but the principle are the same. So the link @RobertHarvey suggest, make use of some sort of event trigger and listener. As i mention, i have already find this solution, but seems overkill for this simple task. I was thinking of something like make the two views use the same instance of one viewModel with all the propertys and methods inside, but i don't know if that's posible because ech view is created from it's viewmodel. – ericpap Apr 11 '15 at 19:12
  • I still think a Dialog Box is the simplest way, unless you have specific requirements. To create a *custom* dialog box, see here: http://www.wpf-tutorial.com/dialogs/creating-a-custom-input-dialog/ – Robert Harvey Apr 11 '15 at 19:20
  • The code you post uses Code-behind. I now it could be easily resolve that way. Also I need to create the modal view itself because not always will it be as simple as "are your sure (yes/no)" – ericpap Apr 11 '15 at 20:34

1 Answers1

2

var dialog = new DialogViewModel();// could be a DialogService if you wish

with in this DialogViewModel or DialogService again your choice how you actually do it.

dialog.Result which in this case would return your confirmation either true or false

var settings = new Dictionary<string, object>(); settings["Owner"] = this; settings["WindowStartupLocation"] = WindowStartupLocation.CenterParent; windowManager.ShowDialog(dialog, null, settings);

if(dialog.Result == true) do the delete on the parent viewmodel.

Or you can do it all with IEventAggregator and a message package. I personally use the first for a lot of things. Sometimes a combination depending on situation.

Most will favor the IDialogService method of things for SoC, and do DI with it to bring it into the viewmodel using it. Then each viewmodel will be responsible its own dialogs. From there you can call ShowDialog since its part of the WindowManager, which you click Yes or No, or what ever you setup for you dialogview. Numerous ways to skin the cat but in the end you want KISS methodology and something that won't break the patterns you are trying to adhere too.. Hell for all it matters you could add it to a viewmodelbase base class for all of your viewmodels to inherit to access globally. All a function how you want your app to behave in the end anyway.

--update--

public class YourViewModel(IWindowManager winMan)
{
     private readonly IWindowManager _winMan;
     public YourViewModel()
     {
       _winMan = winMan;
     }

     public void DeleteCustomer()
     {
        var dialog= new DialogViewModel(); // not best way but...
        var settings = new Dictionary<string, object>();
        settings["Owner"] = this;  //<< Parent
        settings["StartupLocation"] = WindowStartupLocation.CenterParent;
        _winMan.ShowDialog(dialog, null, settings);

        if(dialog.Result)
          //do delete
        else
          //do nothing
     }
}
Yael
  • 1,566
  • 3
  • 18
  • 25
mvermef
  • 3,814
  • 1
  • 23
  • 36
  • Thanks for you answer. I'm trying to test it and i get an error in the last line of code: WindowManager.ShowDialog(dialog, null, settings); wich is "Error 1 An object Reference is required for the non-static field, 'Caliburn.Micro.WindowManager.ShowDialog(object, object, System.Collections.Generic.IDictionary)'" – ericpap Apr 13 '15 at 13:44
  • MEF or SimpleContainer for you container currently? Or Any container at all? – mvermef Apr 13 '15 at 18:12
  • Sorry I can't understand what your asking me at all. I do some test and make this work with: var p = new WindowManager(); p.ShowDialog(dialog, null, settings); and works just fine. The only problem is that it opens a new window, and I need to do it inside the same view. Something like a ContentPresenter. – ericpap Apr 13 '15 at 18:30
  • I was merely presenting a sample of something you could possibly do with Caliburn.Micro, it does still require some infrastructure to get it where you need it for your application. windowmanager just handles showing the dialog what you do with that dialog is up to you. I was giving you a hand with maybe doing something with a "separation of concerns" with how you got the answer to, "do you want to delete ? y/n?" Caliburn.Micro can do it several ways I pointed out 2. Even the MVVMLite option is a similar example of some way to accomplish the task – mvermef Apr 13 '15 at 18:44
  • in the end you will need a custom view "your dialog box" with a viewmodel associated to that dialog. Caliburn.Micro has many examples of this with the WindowManager, or if you want to get really involved the Conductor – mvermef Apr 13 '15 at 18:45
  • Ok, thank you @mvermef. See your point. My idea is, like you put on your last comment, to create my own custom view (with its own viewmodel). The problem is how to comunicate the two viewmodels in a simple way. You did give an idea wich is to have a reference in my main viewmodel a reference to the second viewmodel and then use a property like Result to get the value selected by the user in the second view. Thanks! – ericpap Apr 13 '15 at 18:52