使用Caliburn.Micro MVVM WPF建议视图导航

我是Caliburn Micro的新手,想要了解我的应用程序界面和视图之间导航的路径。 我的想法是有一个MainWindow,它将包含一个按钮菜单,每个按钮与特定视图相关。 每个视图都将存储在单独的WPF UserControl中。 mainWindow还将包含一个TabControl,该TabControl绑定到viewmodel上的ObservableCollection选项卡。 每次单击菜单上的按钮时,我想添加一个内部有ContentPresenter的新选项卡,它将动态加载视图及其相应的视图模型。

所以我的问题:

1)我应该在这里使用屏幕collections吗?

2)UserControl应该实现Screen界面吗?

3)如何告诉MainWindow ViewModel在新添加的选项卡上加载哪个视图来维护viewmodels解耦?

感谢大家提前。

UPDATE

经过大量的阅读和社区的帮助后,我设法解决了这个问题。 这是由此产生的AppViewModel:

class AppViewModel : Conductor.Collection.OneActive { public void OpenTab(Type TipoVista) { bool bFound = false; Screen myScreen = (Screen)Activator.CreateInstance(TipoVista as Type); myScreen.DisplayName = myScreen.ToString(); foreach(Screen miItem in Items) { if (miItem.ToString() == myScreen.ToString()) { bFound = true; ActivateItem(miItem); } } if (!bFound) ActivateItem(myScreen); } public ObservableCollection myMenu { get; set; } public ObservableCollection myDirectLinks { get; set; } public ICommand OpenTabCommand { get { return new RelayCommand(param => this.OpenTab((Type) param), null); } } public AppViewModel() { OpenTab(typeof(ClientsViewModel)); MenuModel menu = new MenuModel(); myMenu = menu.getMenu(); myDirectLinks = menu.getLinks(); } public void CloseTab(Screen param) { DeactivateItem(param, true); } } 

我必须保持ICommand不受OpenTabCommand的影响,因为Caliburn.micro的名称约定似乎不适用于DataTemplate。 希望它可以帮助别人。 谢谢大家

我使用Caliburn.Micro做了一些非常相似的事情,并将其基于示例中包含的SimpleMDI示例,并进行了一些调整以满足我的需求。

与示例中的情况非常相似,我有一个主要的ShellViewModel

 public class ShellViewModel : Conductor.Collection.OneActive { } 

使用包含TabControl的相应ShellView ,将其绑定到ConductorItems属性。

在这个特殊情况下,我在ShellView上也有一个ContextMenu ,绑定(使用Caliburn.Micro约定)到一系列命令,这些命令实例化并Activated各种其他ViewModels (通常使用相应的UserControl ,使用Conductor上的ActivateItem方法) 。

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

在这种情况下,我不需要使用任何特定依赖项或程序中的任何其他位置创建ViewModels

在其他时候,当我需要从应用程序的其他地方触发ViewModel ,我使用了Caliburn.Micro EventAggregator来发布自定义事件(例如OpenNewBrowser ),这可以通过实现相应接口的类来处理(例如IHandle ),因此你的主ViewModel可以有一个简单的Handle方法负责打开所需的View

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

本文档的这一部分可能很有用,尤其是Simple MDI部分。

我在评论中提到的其他代码:

我有时会沿着这些行使用generics方法,确保如果我有一个特定类型的屏幕的现有实例,切换到它,或者如果没有,则创建一个新实例。

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

使用如下:

 public void OpenBrowser() { this.ActivateOrOpen(); }