2013-08-29 60 views
1

希望我可以在这里给出一个明确的问题描述,我在我当前的WPF应用程序分配中实现MVVM。实现WPF应用程序导航mvvm的最佳方式

我所做的是,我创建了一个继承Window的基类,然后每隔一个窗口继承这个类。

public class ApplicationScreenBase : Window 
    { 
     public ApplicationScreenBase() 
     { 
      AppMessenger.Register(this, OnMessageToApp); 
      this.Unloaded += ApplicationScreenBase_Unloaded; 
     } 

     private void ApplicationScreenBase_Unloaded(object sender, RoutedEventArgs e) 
     { 
      AppMessenger.Unregister(this, OnMessageToApp); 
     } 

     private void OnMessageToApp(AppMessage message) 
     { 
      switch (message.MessageType) 
      { 
       case AppMessageType.Navigate: 
        { 
         var CurrentWindow = Activator.CreateInstance(Locator.NavigationPageLocator.LocateNavigateTypeByEnum((NavigationScreens)message.MessageData)) as Window; 
         CurrentWindow.Show(); 
         this.Close(); 
         break; 
        } 
       case AppMessageType.NewWindow: 
        { 
         var CurrentWindow = Activator.CreateInstance(Locator.NavigationPageLocator.LocateNavigateTypeByEnum((NavigationScreens)message.MessageData)) as Window; 
         CurrentWindow.Show(); 
         break; 
        } 
       case AppMessageType.MessageBox: 
        { 
         MessageBox.Show(message.MessageData.ToString()); 
         break; 
        } 
       case AppMessageType.Close: 
        { 
         this.Close(); 
         break; 
        } 
       default: 
        break; 
      } 
     } 
    } 

这是我的导航类返回我要打开的窗口类型。

public static class NavigationPageLocator 
    { 
     public static Type LocateNavigateTypeByEnum(NavigationScreens navigationPage) 
     { 
      switch (navigationPage) 
      { 
       case NavigationScreens.LoginOnline: 
        return typeof(LoginOnline); 
       case NavigationScreens.MainWindow: 
        return typeof(MainWindow); 
       case NavigationScreens.Home: 
        return typeof(Home); 
      } 
      return default(Type); 
     } 
    } 

这是我如何使用AppMessenger

public enum AppMessageType 
    { 
     Navigate, 
     NewWindow, 
     Close, 
     MessageBox 
    } 
    public class AppMessage 
    { 
     public AppMessageType MessageType { get; set; } 
     public object MessageData { get; set; } 
    } 
    public class AppMessenger 
    { 
     public static void Register(object recipient, Action<AppMessage> action) 
     { 
      Messenger.Default.Register<AppMessage>(recipient, action); 
     } 

     public static void Unregister(object recipient, Action<AppMessage> action) 
     { 
      Messenger.Default.Unregister<AppMessage>(recipient, action); 
     } 

     public static void Send(AppMessage message) 
     { 
      Messenger.Default.Send<AppMessage>(message); 
     } 

这好歹是我控制从ViewModel-

AppMessenger.Send(new AppMessage() { MessageType = AppMessageType.Navigate, MessageData = NavigationScreens.Home }); 

流**现在的问题是我注册窗口和成功我发现AppMessenger的一个实例是注册到每个窗口,但是当我通知使者调用某个事件时,它会触发两次。 例如

AppMessenger.Send(new AppMessage() { MessageType = AppMessageType.MessageBox, MessageData = "Authentication failed." }); 

这将显示两个时间MessageBox。请为此提出任何解决方案。

不知道它是如何发射两次。我如何防止这一点。 有什么帮助吗?谢谢。**

回答

0

好了,在这里我发现我的解决方案

public ApplicationScreenBase() 
     { 
      this.Loaded +=ApplicationScreenBase_Loaded; 
      this.Unloaded += ApplicationScreenBase_Unloaded; 
      this.Activated += ApplicationScreenBase_Activated; 
      this.Deactivated += ApplicationScreenBase_Deactivated; 
     } 

     void ApplicationScreenBase_Deactivated(object sender, EventArgs e) 
     { 
      AppMessenger.Unregister(this, OnMessageToApp); 
     } 

     void ApplicationScreenBase_Activated(object sender, EventArgs e) 
     { 
      AppMessenger.Register(this, OnMessageToApp); 
     } 

正在发生的事情是,如果我打开两个窗口,然后AppMessenger发送消息两倍两个窗口目前正与AppMessenger注册。因此,使用Window生命周期,我将Appmessenger注销到后台窗口,并以这种方式注册在forground上,只有一个窗口会注册到AppMessenger,但我怀疑如果两个窗口都处于最小状态的前台,会发生什么情况。希望这可以帮助未来的人。

0

你可以考虑另一个类(WindowManger),它可以为你主窗口。您正在创建一个导航的新窗口。如果窗口已经存在,您可以在WindowManager中进行检查。

+0

谢谢请检查我的问题我发现我的问题中有新东西 –

0

实质上,导航问题是您想要将常常复杂的导航逻辑与关联到每个“页面”内容的UI和业务逻辑分离。这基本上是通过您的NavigationPageLocator类和基于消息的通信系统来实现的。

您似乎正沿着正确的路线实施自己的解决方案,尽管您可能会发现自己不得不做很多“管道工”来实现一些更高级的方案。您可能想看看PRISM documentation关于WPF应用程序中的导航,它提供了一个现成的解决方案。

相关问题