Advice on Views navigation using Caliburn.Micro MVVM WPF

后端 未结 1 961
暖寄归人
暖寄归人 2021-01-06 22:38

I\'m new on Caliburn Micro and want some advice on which path to take to devolop my app interface and navigation between views. My idea is to have a MainWindow which will c

相关标签:
1条回答
  • 2021-01-06 23:20

    I've done something very similar using Caliburn.Micro, and based it on the SimpleMDI example included with the examples, with a few tweaks to fit my needs.

    Much like in the example, I had a main ShellViewModel:

    public class ShellViewModel : Conductor<IScreen>.Collection.OneActive
    {
    }
    

    with a corresponding ShellView containing a TabControl - <TabControl x:Name="Items">, binding it to the Items property of the the Conductor.

    In this particular case, I also had a ContextMenu on my ShellView, bound (using the Caliburn.Micro conventions), to a series of commands which instantiated and Activated various other ViewModels (usually with a corresponding UserControl, using the ActivateItem method on the Conductor.

    public class YourViewModel: Conductor<IScreen>.Collection.OneActive
    {
        // ...
    
        public void OpenItemBrowser()
        {
            // Create your new ViewModel instance here, or obtain existing instance.
            // ActivateItem(instance)
        }
    }
    

    In that case, I didn't require the ViewModels to be created with any particular dependency, or from any other locations in the program.

    At other times, when I've needed to trigger ViewModel from elsewhere in the application, I've used the Caliburn.Micro EventAggregator to publish custom events (e.g. OpenNewBrowser), which can be handled by classes implementing the corresponding interface (e.g. IHandle<OpenNewBrowser>), so your main ViewModel could have a simple Handle method responsible for opening the required View:

    public class YourViewModel: Conductor<IScreen>.Collection.OneActive, IHandle<OpenNewBrowser>
    {
        // ...
    
        public void Handle(OpenNewBrowser myEvent)
        {
            // Create your new ViewModel instance here, or obtain existing instance.
            // ActivateItem(instance)
        }
    }
    

    This section of the documentation will probably be useful, especially the Simple MDI section.

    Additional code I mentioned in the comments:

    I sometimes use a generic method along these lines ensure that if I have an existing instance of a screen of a particular type, switch to it, or create a new instance if not.

    public void ActivateOrOpen<T>() where T : Screen
    {
        var currentItem = this.Items.FirstOrDefault(x => x.GetType() == typeof(T));
    
        if (currentItem != null)
        {
            ActivateItem(currentItem);
        }
        else
        {
            ActivateItem(Activator.CreateInstance<T>());
        }
    }
    

    Used like:

    public void OpenBrowser()
    {
        this.ActivateOrOpen<BrowserViewModel>();
    }
    
    0 讨论(0)
提交回复
热议问题