[英]Advice on Views navigation using Caliburn.Micro MVVM WPF
我是Caliburn Micro的新手,希望获得一些建议,以采取哪些方式来开发我的应用程序界面和视图之间的导航。 我的想法是要有一个MainWindow,它将包含一个按钮菜单,每个按钮都与一个特定的视图相关。 每个视图将存储在单独的WPF UserControl中。 mainWindow还将包含一个TabControl,该TabControl绑定到viewmodel上选项卡的ObservableCollection。 每次单击菜单上的按钮时,我想添加一个带有ContentPresenter的新选项卡,该选项卡将动态加载视图及其对应的viewmodel。
所以我的问题是:
1)我应该在这里使用屏幕集合吗?
2)UserControl应该实现Screen界面吗?
3)如何告诉MainWindow ViewModel在新添加的选项卡上加载哪个视图,以保持视图模型分离?
预先感谢大家。
UPDATE
经过大量阅读和社区的一些帮助后,我设法解决了这个问题。 这是生成的AppViewModel:
class AppViewModel : Conductor<IScreen>.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<MenuItem> myMenu { get; set; }
public ObservableCollection<LinksItem> 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);
}
}
我必须从OpenTabCommand中保留ICommand,因为Caliburn.micro的名称约定似乎无法在DataTemplate中使用。 希望它可以帮助别人。 谢谢大家
我使用Caliburn.Micro
进行了非常相似的操作,并基于示例附带的SimpleMDI
示例进行了一些调整以满足我的需求。
与示例类似,我有一个主要的ShellViewModel
:
public class ShellViewModel : Conductor<IScreen>.Collection.OneActive
{
}
使用包含TabControl
<TabControl x:Name="Items">
的相应ShellView
,将其绑定到Conductor
的Items
属性。
在这种情况下,我的ShellView
上还有一个ContextMenu
,绑定到(使用Caliburn.Micro
约定)一系列命令,这些命令实例化并Activated
了其他各种ViewModels
(通常使用相应的UserControl
,并使用Conductor
上的ActivateItem
方法。
public class YourViewModel: Conductor<IScreen>.Collection.OneActive
{
// ...
public void OpenItemBrowser()
{
// Create your new ViewModel instance here, or obtain existing instance.
// ActivateItem(instance)
}
}
在那种情况下,我不需要使用任何特定的依赖关系或从程序中的任何其他位置创建ViewModels
。
在其他时候,当我需要从应用程序中的其他地方触发ViewModel
,我使用了Caliburn.Micro
EventAggregator
来发布自定义事件(例如OpenNewBrowser
),可以通过实现相应接口的类(例如IHandle<OpenNewBrowser>
),因此您的主ViewModel
可以具有一个简单的Handle
方法来负责打开所需的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)
}
}
我在评论中提到的其他代码:
有时我会沿着这些方式使用通用方法,以确保如果我已有特定类型屏幕的现有实例,请切换到该实例,否则,请创建一个新实例。
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>());
}
}
像这样使用:
public void OpenBrowser()
{
this.ActivateOrOpen<BrowserViewModel>();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.