2013-08-29 2 views
1

Надеюсь, я могу дать ясное описание проблемы здесь, я реализую MVVM в моем текущем назначении приложения WPF.Лучший способ реализовать навигацию в mvvm для приложения wpf

Что я сделал, я создаю базовый класс, который наследует 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

По сути, проблема с навигацией заключается в том, что вы хотите отделить часто сложную навигационную логику с пользовательским интерфейсом и бизнес-логикой, связанными с каждой «страницей» контента. Это достигается, главным образом, с помощью вашего класса NavigationPageLocator и системы связи на основе сообщений.

Вы, кажется, идете по правильным линиям, чтобы реализовать свое собственное решение, хотя вам может понадобиться сделать много «сантехники» для достижения более сложных сценариев. Вы можете взглянуть на PRISM documentation относительно навигации в приложениях WPF, которая предлагает готовое решение.