2012-08-15 29 views
6

我是Caliburn.Micro的新手,我想知道在我的應用程序中處理用戶登錄/註銷週期的最佳方式是什麼。我在網上看到了一些建議,使用空的Shell-View在LoginView和主應用程序視圖之間切換,當然每個視圖都有一個自定義ViewModel。如何處理Caliburn.Micro中的登錄/註銷?

我不太喜歡這個解決方案,因爲對於我來說,這些是2個獨立的窗口,具有非常不同的屬性(標題,圖標,大小),它似乎是一個不潔的解決方案,兩個窗口看起來像另一個。另一個問題是,登錄窗口來自一個實用程序庫,我不控制它,不使用Caliburn.Micro,它是一個普通的舊窗口,當用戶單擊「登錄」時,它會給我一個事件。

我還看到了在Bootstrapper啓動方法中顯示此對話框的建議,但是我看到的問題是用戶可以選擇「註銷」應用程序,該應用程序應該再次顯示「登錄」對話框。我在引導程序中處理視圖之間的切換似乎是錯誤的。

我想要的是某種類似於Caliburn Conductor的ApplicationViewModel或ApplicationController,但不是在窗口內的視圖之間切換,它應該在LoginWindow和MainWindow之間切換,並且還應該處理關閉整個應用程序(也需要註銷)。在激活時,它將顯示LoginWindow,處理登錄事件,然後切換到主窗口(Shell)。如果用戶選擇「LogOut」,事件應該再次啓動到ApplicationViewModel/Controller,它將關閉/關閉MainWindow,執行註銷,然後再次顯示LoginDialog。類似的關閉事件將執行註銷,但然後關閉整個應用程序。

所以我的問題是:

  1. 你覺得這個怎麼樣的解決方案,做您有其它/更好的?
  2. 我該如何實施? ;-)

非常感謝!

+0

你是WPF還是WinForms?登錄窗口還會執行驗證用戶的實際工作,還是您必須處理「登錄」事件並執行此操作? – Kioshiki 2012-08-20 17:15:23

+1

WPF窗口,它引發了一個登錄事件,我使用從IoC容器獲得的身份驗證服務處理該事件。 – aKzenT 2012-08-20 21:09:43

回答

16

我認爲解決您的問題相當簡單。

簡而言之,您將創建一個ViewModel作爲Shell,並在應用程序啓動時使用登錄窗口表示。如果用戶成功登錄,則此窗口關閉,並且在內容窗口中顯示相同的viewModel實例。如果用戶正在註銷,則會再次顯示登錄窗口。

首先創建一個接口IShell的暴露兩位代表LoginSuccessfulLogout

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

接着創建一個類ShellViewModel它實現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是操作其可以是綁定到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方法被調用,當前窗口被通過在ShellViewModel調用TryClose關閉。同時,通過將Application.ShutdownMode設置爲OnExplicitShutdown,可以防止應用程序被關閉。然後使用窗口管理器,通過將「登錄」作爲上下文信息傳遞給windowManager,以登錄模式創建另一個窗口。這實際上是相同的ViewModel,但是,具有不同的視覺表示。

對於Logout你正在做同樣的事情。

爲了得到這個使用卡利約定的工作,你需要爲這裏看到一個特殊的項目結構(並解釋there): enter image description here

現在我挑戰你利用這個代碼,並創建一個小示例應用程序。創建Login視圖(使用按鈕或其他方式進行登錄),並使用LoginSuccessful/Logout方法創建帶有註銷按鈕的Content視圖。

這將以最少的代碼和類來解決您的問題。希望這會對你有所幫助。

+0

我很感興趣,這也是如此。在你的例子中,ShellViewMode是什麼?它應該是ShellViewModel還是隻是一個字符串?另外aKzenT說登錄窗口已經存在,那麼這會如何影響你的設計呢? – Kioshiki 2012-08-18 19:00:54

+0

ShellViewMode是一個錯字。當然,這是一個將上下文信息傳遞給窗口管理器的字符串。您也可以將此上下文設置爲枚舉,這將是一個好主意。 對於現有的登錄窗口,將此xaml放入Login.xaml,並將UI設置爲viewModel中現有的Actions。這可能不那麼複雜,因爲大多數時候,登錄對話框只是一個帶有用戶名/密碼文本框的登錄/取消按鈕。然後可以通過ShellViewModel完成Autorisation,或者使用某個驗證代理擴展接口以解耦此邏輯,並使其在運行時變爲可變。 – 2012-08-19 13:33:52

+1

我認爲在這種情況下字符串是正確的,因爲你說一個枚舉會更好。我認爲你現在的登錄窗口仍然沒有和我一樣的想法(儘管我可能有錯誤的想法)。我正在考慮一種情況,您必須使用二進制程序集中的現有窗口,可能是在擁有WPF窗口的公司中,或者甚至是必須用於公開事件等登錄過程的WindowsForms窗體(可能是由於驗證等)。我認爲這很難找到一個乾淨的解決方案。 – Kioshiki 2012-08-19 13:57:39

3

我已經開始創建基本上可行的東西,但可能需要更多的工作才能真正實用。完整的評論和來源可以在我的網站上找到這個職位Caliburn.Micro Login Window sample

我使用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);