使用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
–
,将其绑定到Conductor
的Items
属性。
在这个特殊情况下,我在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(); }