How to open new Window?

Nov 21, 2010 at 1:30 PM
Edited Nov 21, 2010 at 1:31 PM

Hello,

just another question raised up during my CM migration. I would like to know how I can open another window using CM?
I've now my application window with a model derived from conductor class and a method that shall open the new window.
From the screens & conductos documentation I thought this is done just with the ActivateItem command but that doesn't works.
Here is the code from my model:

   public class ApplicationModel : Conductor<object>
    {
        public event System.EventHandler<ActivationProcessedEventArgsActivationProcessed;

        public ApplicationModel()
        {
        }

        public void ShowApplicationSettings()
        {
            ActivateItem( new ApplicationSettingsModel() );
        }

        public bool CanShowApplicationSettings
        {
            get { return true; }
        }

        public bool IsApplicationMenuEnabled
        {
            get { return true; }
        }

        public string ApplicationTitle
        {
            get { return "MVVM Test"; }
        }
    }

Thanks in advance.
Coordinator
Nov 21, 2010 at 1:55 PM

Calling ActivateItem activates the model you pass to it and sets it as the Conductor's ActiveItem property. In order to see it, you would need to have a ContentControl setup either by convention or with a View.Model attached property, bound to ActiveItem. This does not open a new window. It only composes an item into an existing space. To show windows, use the IWindowManager.

Nov 21, 2010 at 2:01 PM

Hmm, how have I to do that so that my new window is handled correctly by CM? Can please give me a short code example?

 

Nov 21, 2010 at 2:13 PM

Ok, I got it working by extending my class to this:

    public class ApplicationModel : Conductor<object>, IWindowManager
    {
        public void ShowApplicationSettings()
        {
            Show(new ApplicationSettingsModel());
        }

        #region IWindowManager Member
        //***************************

        public void Show(object rootModel, object context = null)
        {
            ActivateItem(rootModel);
            var wm = IoC.Get<WindowManager>();
            if (wm != null)
                wm.Show(rootModel, context);
            else
                throw new Exception("Unable to get window manager reference");
        }

        public bool? ShowDialog(object rootModel, object context = null)
        {
            throw new System.NotImplementedException();
        }

        #endregion
    }

Is that enough for CM to handle the new Model and it's presentation layout (the new window)? Do I have to call ActivateItem for the current model after the window has been closed
or is it just some kind of initialisation?

 

Coordinator
Nov 21, 2010 at 7:05 PM

I'm confused by what you are doing here. It's not the way I would typically use these APIs. Can you give me some more information describing the general architecture and what you are trying to accomplish? Perhaps I can better recommend a solution then.

Nov 21, 2010 at 9:24 PM
Edited Nov 21, 2010 at 9:25 PM
EisenbergEffect wrote:

I'm confused by what you are doing here. It's not the way I would typically use these APIs. Can you give me some more information describing the general architecture and what you are trying to accomplish? Perhaps I can better recommend a solution then.

Hello,

the model is part of my application window (aka MainWindow) and it has a button on that I want to open an new window (new view model) with the application settings. I thouth about you're concerns and maybe my solution was really a bit to simple. A much cleaner and better way would be a derived class from the CM window manager, that handles the call??

Coordinator
Nov 22, 2010 at 2:42 AM

Why can't you just use the WindowManager as is?

Nov 22, 2010 at 12:59 PM

Hello Rob,

ok, maybe I should provide some more information about what I'm trying to do. In my MainWindow.xaml I've the following line:

<button x:Name="ShowApplicationSettings" Content="Open Application Settings />

which calls my method in the view model (ShowApplicationSetting). The purpose of the method is to open a new view, which has
also an view model (ApplicationSettingsModel). This view should be display in a new dialog window. You recomended me already
to use the IWindowManager interface. The code above that accesses the window manager over the IoC was in another article in this
forum, so I grabbed and changed it. 

I really would like to get a better acknowledge of you MVVM framework and I'm sure you've better solutions for this.

Thanks in advance.

 

 

Coordinator
Nov 22, 2010 at 2:21 PM

It sounds like you might be over-complicating this scenario. In your ShowApplicationSettings method, all you need to do is call ShowDialog on the WindowManager, passing it an instance of ApplicationSettingsViewModel.  If you are using IoC, you should have configured the WindowManager (and probably ApplicationSettingsViewModel) as a singleton service registered as IWindowManager. This is what the templates do and mostly what I show in all the samples. You should be able to have an IWindowManager injected into your ApplicationModel this way. So your code might look like this:

public class ApplicationModel{
   IWindowManager windowManager;
   ApplicationSettingsViewModel applicationSettings;

   public ApplicationModel(IWindowManager windowManager, ApplicationSettingsViewModel applicationSettings){
      this.windowManager = windowManager;
      this.applicationSettings = applicationSettings;
   }

   public void ShowApplicationSettings(){
      windowManager.ShowDialog(applicationSettings);
   }
}

Nov 23, 2010 at 7:48 AM
Edited Nov 23, 2010 at 9:33 AM

Hey Rob,

you're solution is really great. Thanks for it. I definetely was thinking to much in one direction. Please can you give me anotther advise how I bind this
to a menuitem? I discovered in another threat that a menuitem is a complex element and my only workaround until now is a hack in my codebehind
which reroutes the command to the viewmodel:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            CommandBindings.Add(new CommandBinding(ApplicationCommands.Properties, OpenApplicationSettings));
            CommandBindings.Add(new CommandBinding(ApplicationCommands.Close, CloseApplication));
        }

        private void OpenApplicationSettings(object sender, RoutedEventArgs e)
        {
            if (DataContext is MainWindowModel)
                ((MainWindowModel)DataContext).ShowApplicationSettings();
        }   

        private void CloseApplication(object sender, RoutedEventArgs e)
        {
            Close();
        }
    }
That would be my final question to this topic, promised. 
Thanks again in advance.