2012-08-15 4 views
6

私はCaliburn.Microが新しく、私のアプリケーションでユーザーのログイン/ログアウトサイクルを処理する最良の方法は何か不思議です。私は、LoginViewとメインのアプリケーションビューを切り替える空のShell-Viewを使用して、これを実装するためにいくつかの提案をオンラインで見てきました。それぞれカスタムViewModelがあります。Caliburn.Microでログイン/ログアウトを処理するにはどうすればよいですか?

私はこれらが非常に異なるプロパティ(タイトル、アイコン、サイズ)を持つ2つの別々のウィンドウであり、2つのウィンドウを1つのウィンドウを他のウィンドウと同じように変更するのは汚れているようです。もう1つの問題は、ログインウィンドウが私が制御しないユーティリティライブラリから来て、Caliburn.Microを使用していないということです。ユーザーが「ログイン」をクリックしたときに私にイベントを与える普通の古いウィンドウです。

また、このダイアログをブートストラップの起動方法で表示することを提案しましたが、私が見ている問題は、ユーザーがログインダイアログを再度表示する必要があるアプリケーションの「ログアウト」を選択できることです。ブートストラップのビュー間の切り替えを処理するのは間違っているようです。

私が望むのは、Caliburn Conductorのように動作するApplicationViewModelやApplicationControllerのようなものですが、ウィンドウ内のビューを切り替えるのではなく、LoginWindowとMainWindowを切り替える必要があります。アプリケーション全体(ログアウトも必要)。アクティベーションでは、LoginWindowが表示され、Loginイベントを処理してメインウィンドウ(シェル)に切り替えます。ユーザーが "LogOut"を選択した場合、イベントはApplicationViewModel/Controllerに再度吹き込み、MainWindowを非アクティブ化/閉じる、ログアウトを実行して、再度LoginDialogを表示する必要があります。同様のCloseイベントはLogoutを行いますが、アプリケーション全体をシャットダウンします。

だから私の質問は以下のとおりです。

  1. あなたはこのソリューションについてどう思いますか、あなたは別の/より良いものを持っていますか?
  2. これはどのように実装しますか? ;-)

ありがとうございます!

+0

をログアウトイベントは次のようになりますあなたはWPFかWinFormsですか?また、ログインウィンドウは、ユーザーを認証する実際の作業を行うか、「ログイン」イベントを処理して行う必要がありますか? – Kioshiki

+1

WPFウィンドウを開き、IoCコンテナから取得した認証サービスを使用して処理するログインイベントを発生させます。 – aKzenT

答えて

16

あなたの問題に対する解決方法はかなり簡単だと思います。

簡単に言えば、アプリケーションの起動時にログインウィンドウで表される1つのViewModelをシェルとして作成しています。ユーザーが正常にログインすると、このウィンドウは閉じられ、viewModelの同じインスタンスがコンテンツウィンドウに表示されます。ユーザーがログアウトしている場合は、ログインウィンドウが再度表示されます。全ての

最初は、二つのデリゲートLoginSuccessfulLogout

public interface IShell 
    { 
     Action LoginSuccessful { get; set; } 
     Action Logout { get; set; } 
    } 

次に作成IShell

public class ShellViewModel : Screen, IShell 
    { 
     public ShellViewModel() 
     { 
      LoginSuccessful = delegate { }; 
      Logout = delegate { }; 
     } 

     public Action LoginSuccessful { get; set; } 
     public Action Logout { get; set; } 

     public void DoLogin() 
     { 
      LoginSuccessful(); 
     } 

     public void DoLogout() 
     { 
      Logout(); 
     } 
    } 

方法DoLoginDoLogoutができるアクションである実装クラスShellViewModelを公開インターフェースISHELLを作成しますButtonまたはあなたに適したコントロールにバインドされています。

次の手順では、ブートストラップの​​を上書きします。これは、あなたが選択したIoCフレームワークによってエクスポートされたWindowManagerShellViewModelのインスタンスを持っていることを前提としています。これに

protected override void OnStartup(object sender, StartupEventArgs e) 
     { 
      var windowManager = IoC.Get<IWindowManager>(); 
      var viewModel = IoC.Get<IShell>(); 

      viewModel.LoginSuccessful = 
       () => GuardCloseAndReopen("Content"); 

      viewModel.Logout = 
       () => GuardCloseAndReopen("Login"); 

      windowManager.ShowWindow(viewModel, "Login"); 
     } 

     private void GuardCloseAndReopen(string shellViewMode) 
     { 
      var windowManager = IoC.Get<IWindowManager>(); 
      var shellScreen = IoC.Get<IShell>() as Screen; 

      Application.ShutdownMode = ShutdownMode.OnExplicitShutdown; 

      shellScreen.TryClose(); 

      Application.ShutdownMode = ShutdownMode.OnLastWindowClose; 

      windowManager.ShowWindow(shellScreen, shellViewMode); 
     } 

トリックがある:DoLogoutメソッドが呼び出された場合、現在のウィンドウがShellViewModelTryCloseを呼び出すことによって閉じられます。同時に、Application.ShutdownModeOnExplicitShutdownに設定して、アプリケーションのシャットダウンを防止します。次に、ウィンドウマネージャを使用して、ウィンドウマネージャにコンテキスト情報として「ログイン」を渡して、ログインモードで別のウィンドウを作成します。ただし、これは実際には同じ視点表現を持つ同じViewModelです。

Logoutについては、まったく同じことをやっています。

これはカリバーンの表記法を使用して作業するには、あなたがここに見られるように、特別なプロジェクトの構造を必要とする(とthereを説明): enter image description here

は今、私はあなたがこのコードを取ると少しのサンプルアプリケーションを作成するために挑戦しています。 Loginビュー(ボタンなどでログインします)を作成し、LoginSuccessful/Logoutメソッドを使用してログアウトボタンでContentビューを作成します。

これにより、最小限のコードとクラスで問題が解決されます。これがあなたに役立つことを願っています。

+0

これはどのようにうまくいくか興味があります。あなたの例では、ShellViewModeは何ですか?それはShellViewModelか多分ただの文字列でしょうか?また、KzenTは、ログインウィンドウがすでに存在していたので、どのようにこれがあなたのデザインに影響するかもしれないと述べましたか? – Kioshiki

+0

ShellViewModeはタイプミスです。もちろんこれはコンテキスト情報をウィンドウマネージャに渡す文字列です。このコンテキストを列挙型に設定することもできます。これは良い考えです。 既存のログインウィンドウでは、このxamlをLogin.xamlに配置し、UIをviewModel内の既存のアクションに設定します。ほとんどの場合、ログインダイアログは単にユーザー名/パスワードのテキストボックスを持つログイン/キャンセルボタンなので、これは複雑ではないかもしれません。次に、AutorisationをShellViewModelで実行するか、またはこのロジックをデカップリングして実行時に変更可能にするために、一部の検証デリゲートでインターフェイスを拡張します。 –

+1

私は、列挙型が正しいと思った。私はあなたがまだ既存のログインウィンドウで私と同じアイデアを持っていないと思う(私は間違った考えがあるかもしれない)。私は、バイナリアセンブリから既存のWindowを使用しなければならない状況を考えています。WPFウィンドウや、イベントなどを公開するログインプロセスに使用する必要があるWindowsFormsフォームさえある会社では検証など)。私はそれがきれいな解決策を見つけるのは非常に難しいと思う。 – Kioshiki

3

私は基本的には動作するものを作成することに行きましたが、本当に使えるようにするにはもう少し作業が必要です。完全なコメントと情報源は、この投稿Caliburn.Micro Login Window sample私のウェブサイトで見つけることができます。

私は、2つのウィンドウ間の遷移を制御するために、Caliburn.MicroのIEventAggregatorを使用しました。あなたはログイン画面を開くには、このコードを取得する:

public void Handle(LoginEvent message) 
{ 
    LoginWindow loginWindow = new LoginWindow(); 
    loginWindow.Login += new EventHandler<LoginEventArgs>(this.LoginWindow_Login); 
    loginWindow.Cancel += new EventHandler(LoginWindow_Cancel); 
    loginWindow.ShowDialog(); 
} 

この同じソースがログアウトイベントが公開されたときにアプリが開き、最初の時間の両方のために使用されています。

public void Handle(LogoutEvent message) 
{ 
    Application.Current.ShutdownMode = ShutdownMode.OnExplicitShutdown; 
    message.Source.TryClose(); 
    Application.Current.ShutdownMode = ShutdownMode.OnLastWindowClose; 
    this.events.Publish(new LoginEvent()); 
} 

ログインに成功すると、それはViewModelに基づいているメインウィンドウ開くには、このコードを使用しています:あなたは「昔ながらの窓」を行うと言うとき

ContentViewModel viewModel; 
viewModel = IoC.Get<ContentViewModel>(); 
viewModel.Username = e.Username; 
this.windowManager.ShowWindow(viewModel); 
関連する問題