1

ここで問題を明確に説明できることを願っています。現在の WPF アプリケーションの割り当てに MVVM を実装しています。

私がしたことは、ウィンドウを継承する基本クラスを作成し、他のすべてのウィンドウがこのクラスを継承することです。

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 の単一のインスタンスがウィンドウごとに登録されていることがわかりましたが、メッセンジャーにイベントを呼び出すように通知すると、2 回発生します。例えば

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

これにより、MessageBox が 2 回表示されます。これに対する解決策を提案してください。

どうやって2回発射したのかわからない。どうすればこれを防ぐことができますか。何か助けはありますか?ありがとう。**

4

3 に答える 3

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);
        }

何が起こっているかというと、2 つのウィンドウを開くと、両方のウィンドウが現在 AppMessenger に登録されているため、AppMessenger がメッセージを 2 回送信します。したがって、ウィンドウライフサイクルを使用して、Appmessengerをバックグラウンドにあるウィンドウに登録解除し、この方法でフォアグラウンドにあるウィンドウを登録すると、AppMessengerに登録されるウィンドウは1つだけですが、両方のウィンドウが最小化状態でフォアグラウンドにあるとどうなるか疑問です. これが将来誰かを助けることを願っています。

于 2013-08-29T12:45:58.733 に答える
0

基本的に、ナビゲーションの問題は、しばしば複雑なナビゲーション ロジックを、コンテンツの各「ページ」に関連付けられた UI およびビジネス ロジックと切り離したいということです。これは基本的に、NavigationPageLocatorクラスとメッセージベースの通信システムによって実現されます。

より高度なシナリオを実現するには、多くの「配管」を行う必要があることに気付くかもしれませんが、独自のソリューションを実装するために正しい方向に進んでいるようです。すぐに実装できるソリューションを提供する WPF アプリケーションでのナビゲーションに関する PRISM ドキュメントを参照してください。

于 2013-08-29T08:20:25.133 に答える