Setting the DialogResult from the ViewModel

Aug 7, 2010 at 5:11 PM
Edited Aug 7, 2010 at 5:56 PM

What would be the Caliburn way for setting the DialogResult for a ChildWindow (a popup) from inside the ViewModel? I've considering extending the IWindowManager interface for that, but for now, I'll use the IViewAware interface instead.

Aug 7, 2010 at 9:22 PM

Screen.TryClose(bool? dialogResult) should do exactly what you need.

Aug 8, 2010 at 6:16 AM

That overload is not part of the SilverLight version. However, I understood that screens and conductors are not really necessary in a SL4 business applicationt that uses the frame mechanism.

Aug 8, 2010 at 6:12 PM

Sorry, I missed you were in a SL application.
You might try to implement an extension method following the line of the WPF implementation: if VM implements IViewAware interface (or inherits from Screen), you can access the view bound to it and set the dialog result.

I'm not familiar enough with SL Navigation Framework to give you an advice, but I saw a recent rant of Rob against it: http://twitter.com/EisenbergEffect/status/20494599391

My (superficial) impressions is that it is mixing in the vies side some application concerns that should better live in the VM side; anyone has a better knowledge of it?

Coordinator
Aug 8, 2010 at 6:26 PM
Have a look at the FrameAdapter in the WP7 version of the framework. It should be able to be re-purposed for the SL Nav framework.
Aug 9, 2010 at 5:09 AM

I'm already using the frame adapter, but my question is unrelated to that.

Coordinator
Aug 9, 2010 at 2:26 PM
Personally, I don't use the DialogResult very often. Typically, I create a custom VM for my dialog which has properties with the relevant information (including whether or not the dialog was canceled). I then use the data from the VM itself after it has been closed.
Aug 13, 2010 at 7:33 PM
EisenbergEffect wrote:
Personally, I don't use the DialogResult very often. Typically, I create a custom VM for my dialog which has properties with the relevant information (including whether or not the dialog was canceled). I then use the data from the VM itself after it has been closed.

Hi Rob,

First off, thank you so much for this framework (as well as your Mix10 session, video and GameLibrary sample). Superb work and greatly GREATLY appreciated.

Second, any chance you could post a quick example to show how a "parent" viewmodel can open a custom viewmodel and retrieve data from it?
Here's my starter sample:

            var wm = new WindowManager();
            var dvm = IoC.Get<IScreen>("SampleProject.Views.DialogViewModel") as DialogViewModel;
            dvm.Message = "Hello from parent screen";
            dvm.MessageDetails = "Some detailed info to show on the dialog";
            wm.ShowDialog(dvm, this);
            // check if user cancels out of the Dialog. How?
            // retrieve data from the Dialog window. How?

Aug 21, 2010 at 10:06 PM
Kariz_G wrote:
EisenbergEffect wrote:
Personally, I don't use the DialogResult very often. Typically, I create a custom VM for my dialog which has properties with the relevant information (including whether or not the dialog was canceled). I then use the data from the VM itself after it has been closed.

Hi Rob,

First off, thank you so much for this framework (as well as your Mix10 session, video and GameLibrary sample). Superb work and greatly GREATLY appreciated.

Second, any chance you could post a quick example to show how a "parent" viewmodel can open a custom viewmodel and retrieve data from it?
Here's my starter sample:

I just figured out a solution to the same problem for myself.  What I did was -

  1. My viewmodel inherhits " PropertyChangedBase, IViewAware, IDeactivate"
  2. I'm using the ViewModel first approach, so the VM contains a local copy of the view.
  3. I implemented IDeactivate as follows in my VM -
       public event EventHandler<DeactivationEventArgs> AttemptingDeactivation;
            public void Deactivate(bool close)
            {
                var e = new DeactivationEventArgs {WasClosed = true};
                AttemptingDeactivation(this, e);
            }
    
            public event EventHandler<DeactivationEventArgs> Deactivated;
    
  4. Then in the routine that invoked the VM, added an event handler to AttemptingDeactivation event
      void EditWindow_Closing(object sender, DeactivationEventArgs e)
  5.  In the event handler, I queried the VM to get the results I needed.
Good Luck

 


Aug 24, 2010 at 9:23 AM

Rob, could you please let us know if the solution proposed by photo_tom is what you intended as well? Because, for unit testing purposes, I don't like using the IoC class in my ViewModel to inject any dependencies.

Coordinator
Aug 24, 2010 at 2:18 PM

I wouldn't use the IoC directly in the VM. But other than that, I think the approach is good. I usually inject a Func<T> for creating the VMs or if using MEF, Lazy<T>. Another approach I have used is to build an IResult for this. So you might have code like this:

var viewModel = mefLazyVM.Value;

yield return Show.Modal(viewModel);

//do something with the view model's result here

If you don't need the result, you can just do something like this:

yield return Show.Modal<MyViewModel>();

Under the covers, the IResult would use the IWindowManager. It would also wire up to the Deactivated event and fire the IResult.Completed event after deactivation. This would cause your method to "pause" until the user dismissed the modal. This is my preferred technique, since modals are usually initiated by a user. Also, this is pretty easy to test. Simply provide a fake factory and enumerate the results. Do not call execute on the results, because you are not testing them, you are testing what results are yielded and what are done with them. Even if you are using Caliburn.Micro, it might be worth the time to look through the ShellFramework present in the full version of Caliburn. Some of these pieces are present there and could be easily ported to CM in as suits your needs. Just have a look in the Results namespace.

Aug 24, 2010 at 3:17 PM

Thank you Rob.