Advice on Views navigation using Caliburn.Micro MVVM WPF

一世执手 提交于 2019-12-01 12:16:32

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>();
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!