WPF Caliburn.Micro - 最佳的方式在辛格窗口应用程序导航
- 我的历史:
我正在开发一个WPF应用程序,这将在全屏幕触摸屏上运行。在我的应用程序中导航只能通过点击每个页面上的按钮来完成(“返回”或“注销”)。WPF Caliburn.Micro - 最佳的方式在辛格窗口应用程序导航
这不是一个通用应用程序,但它看起来像。
-
假设项目:
- 应用将在全屏模式Windows 7中的触摸屏上运行。
- 我正在使用Caliburn.Micro MVVM框架。
问题和问题:
我有1个窗和3用户控件(和的ViewModels)Concept art
Window ShellView
UserControl LoginView
UserControl OrdersView
UserControl OrderDetailView
当应用程序开始,我设定LoginView为默认并通过使用CM Conductor ActivateItem方法加载它,但我不知道如何从UserControl设置另一个视图,如LoginView
我已阅读:this question但这并不包括我的情况 和this answer但我很难理解。
我的想法:
- 使静态方法ShellViewModel,如:
ShellViewModel在ShellViewModel
public static void setOrdersView() {
ActivateItem(new OrdersViewModel());
// Error : An object reference is required for the non-static field, method, or property 'Caliburn.Micro.ConductorBase<object>.ActivateItem(object)
}
ShellViewModel.setOrdersView();
- 化妆监听器,并从子视图模型发送事件(但现在我不知道如何实现它)
问题:在这种情况下处理导航的最佳方式是什么?
- 应用架构:
ShellView
<Window>
<ContentControl x:Name="ActiveItem" />
</Window>
ShellViewModel
public class ShellViewModel : Conductor<object>, IShell
{
public ShellViewModel()
{
LoadDefault();
}
public void LoadDefault()
{
ActivateItem(new LoginViewModel());
}
}
LoginView
<UserControl>
<Button x:Name="Login" />
</UserControl>
LoginViewModel
public class LoginViewModel : PropertyChangedBase
{
public void Login() {
if (LoginManager.Login("User", "Password")) {
// How to redirect user to OrdersView?
}
}
}
我有一个shell窗口和内部激活许多意见和某些对话窗口类似的应用。 您应该使用EventAggregator这些需求和Caliburn模式已经实现。
如何实现:
最低Shell
签名
public class ShellViewModel : Conductor<object>,
IHandle<ChangePageMessage>,
IHandle<OpenWindowMessage>
你需要内部的两个字段(第二个是对话框):
public IEventAggregator EventAggregator { get; private set; }
public IWindowManager WindowManager { get; private set; }
我设置单个实例通过IoC的那些对象。您也可以将它们定义为单身人士。 EventAggregator需要在实施IHandle
的对象上订阅。
EventAggregator.Subscribe(this); //You should Unsubscribe when message handling is no longer needed
处理程序执行:
public void Handle(ChangePageMessage message) {
var instance = IoC.GetInstance(message.ViewModelType, null);//Or just create viewModel by type
ActivateItem(instance);
}
public void Handle(OpenWindowMessage message) {
var instance = IoC.GetInstance(message.ViewModelType, null);//Or just create viewModel by type
WindowManager.ShowWindow(instance);
}
消息事件聚合只能标记类,但有时它的更多参数传递像我们这样OpenWindowMessage
和ChangePageMessage
类是有用的 - 他们是由内容完全相似,因此例如:
public class OpenWindowMessage {
public readonly Type ViewModelType;
public OpenWindowMessage(Type viewModelType) {
ViewModelType = viewModelType;
}
}
所有您的viewModels也可以订阅EventAggregator实例和Ha发送一些用于通信的消息,甚至用于初始参数。我几乎对每个viewModel都有类似MyViewModelInitMessage
的类,并且只是一起使用两个发布方法。
EventAggregator.Publish(new ChangePageMessage(typeof(MyViewModel)));
EventAggregator.Publish(new MyViewModelInitMessage("...all needed parameters"));
所以,当我出版这两个 - 矿ViewModel
就会被激活,那么订阅EventAggregator
(不要忘了做,或者第二个消息处理永远不会发生),并且将处理其InitMessage
右后。
现在用EventAggregator您可以在当前订阅它的所有ViewModel之间发送消息。
这似乎很常见的解决方案。