1

希望我能在这里给出一个清晰的问题描述,我在我当前的 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。请为此提出任何解决方案。

不知道怎么打了两次。我该如何防止这种情况。有什么帮助吗?谢谢。**

4

3 回答 3

0

本质上,导航的问题是您希望将通常复杂的导航逻辑与与每个内容“页面”相关联的 UI 和业务逻辑解耦。这基本上是通过您的NavigationPageLocator课程和基于消息的通信系统来实现的。

您似乎正在沿着正确的路线实施自己的解决方案,尽管您可能会发现自己必须做很多“管道”来实现一些更高级的场景。您可能需要查看有关 WPF 应用程序中导航的PRISM 文档,该文档提供了一个现成的解决方案。

于 2013-08-29T08:20:25.133 回答
0

您考虑另一个可以为您管理窗口的类(WindowManger)。您也在为导航创建一个新窗口。如果窗口已经存在,您可以在此处从 WindowManager 检查。

于 2013-08-29T08:05:12.867 回答
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 注册。因此,使用窗口生命周期,我将 Appmessenger 注销到后台窗口并以这种方式注册前台窗口,只有一个窗口将注册到 AppMessenger,但我怀疑如果两个窗口都在前台处于最小化状态会发生什么。希望这可以帮助将来的人。

于 2013-08-29T12:45:58.733 回答