2012-08-15 34 views
6

Tôi mới sử dụng Caliburn.Micro và tôi tự hỏi cách tốt nhất để xử lý các chu kỳ Đăng nhập/Đăng xuất của người dùng trong ứng dụng của tôi là gì. Tôi đã thấy một số gợi ý trực tuyến để thực hiện điều này bằng cách sử dụng một Shell-View trống mà chuyển đổi giữa LoginView và khung nhìn ứng dụng chính, mỗi một ViewModel tùy chỉnh tất nhiên.Làm cách nào để xử lý Đăng nhập/Đăng xuất trong Caliburn.Micro?

Tôi không thực sự thích giải pháp này, vì với tôi đây là 2 cửa sổ riêng biệt với các thuộc tính rất khác nhau (Tiêu đề, Biểu tượng, Kích thước) và có vẻ như một giải pháp ô uế hai thay đổi một cửa sổ trông giống như cửa sổ kia. Một vấn đề nữa là, Cửa sổ Đăng nhập xuất phát từ một thư viện tiện ích mà tôi không kiểm soát và không sử dụng Caliburn.Micro, đó là một cửa sổ cũ đơn giản mang đến cho tôi một sự kiện khi người dùng nhấp vào "Đăng nhập".

Tôi cũng thấy các đề xuất để hiển thị Hộp thoại này trong phương pháp khởi động Bootstrapper, nhưng vấn đề tôi thấy là người dùng có thể chọn "Đăng xuất" của ứng dụng sẽ hiển thị lại hộp thoại Đăng nhập. Nó có vẻ sai với tôi để xử lý việc chuyển đổi giữa các khung nhìn trong Bootstrapper. Những gì tôi muốn là có một số loại ApplicationViewModel hoặc ApplicationController hoạt động giống như một Caliburn Conductor, nhưng thay vì chuyển đổi giữa các khung nhìn bên trong một cửa sổ, nó nên chuyển đổi giữa LoginWindow và MainWindow và cũng nên xử lý việc đóng cửa của toàn bộ ứng dụng (cũng yêu cầu Đăng xuất). Khi kích hoạt nó sẽ hiển thị LoginWindow, xử lý sự kiện Login và sau đó chuyển sang cửa sổ chính (Shell). Nếu người dùng chọn "LogOut", sự kiện sẽ bong bóng lên đến ApplicationViewModel/Controller một lần nữa sẽ tắt/đóng MainWindow, thực hiện Đăng xuất và sau đó hiển thị lại LoginDialog. Tương tự như một sự kiện Close sẽ thực hiện Logout, nhưng sau đó Shutdown toàn bộ ứng dụng.

Vì vậy, câu hỏi của tôi là:

  1. Bạn nghĩ gì về giải pháp này và làm bạn có một/một tốt hơn?
  2. Làm cách nào để triển khai tính năng này? ;-)

Cảm ơn rất nhiều!

+0

Khi bạn nói "đồng bằng Window cũ" làm bạn WPF hoặc WinForms? Cửa sổ đăng nhập cũng thực hiện công việc thực tế để xác thực người dùng hay bạn phải xử lý sự kiện "Đăng nhập" và thực hiện điều đó? – Kioshiki

+1

WPF cửa sổ và nó đặt ra một sự kiện đăng nhập mà tôi xử lý bằng cách sử dụng một dịch vụ xác thực mà tôi nhận được từ container IoC của tôi. – aKzenT

Trả lời

16

Tôi nghĩ giải pháp cho vấn đề của bạn khá dễ dàng.

Tóm lại, bạn đang tạo một ViewModel là Shell được trình bày bằng Cửa sổ đăng nhập khi ứng dụng bắt đầu. Nếu người dùng đăng nhập thành công cửa sổ này đóng và cùng một thể hiện của viewModel được hiển thị trong một cửa sổ nội dung. Nếu người dùng đang đăng xuất, Cửa sổ đăng nhập sẽ hiển thị lại.

Trước hết tạo ra một IShell giao diện đó cho thấy hai đại biểu LoginSuccessfulLogout

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

Tiếp theo, tạo một lớp ShellViewModel mà thực hiện 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(); 
     } 
    } 

Các phương pháp DoLoginDoLogout là Actions có thể được liên kết với một số Button hoặc bất kỳ điều khiển nào phù hợp với bạn.

Bước tiếp theo là ghi đè OnStartupMethod trong Bootstrapper của bạn. Cơ sở này mà bạn có một thể hiện của WindowManagerShellViewModel được xuất bởi Khung IoC mà bạn chọn.

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

Bí quyết vấn đề này là: Nếu phương pháp DoLogout được gọi, cửa sổ hiện tại được đóng lại bằng cách gọi TryClose trên ShellViewModel. Đồng thời bạn ngăn không cho ứng dụng bị tắt bằng cách đặt Application.ShutdownMode thành OnExplicitShutdown. Sau đó, bằng cách sử dụng trình quản lý cửa sổ, bạn tạo một cửa sổ khác trong Chế độ đăng nhập bằng cách chuyển "Đăng nhập" dưới dạng thông tin Ngữ cảnh đến trình quản lý cửa sổ. Đây thực sự là cùng một ViewModel, tuy nhiên, với một đại diện trực quan khác nhau.

Đối với Logout bạn cũng đang làm điều tương tự.

Để có được điều này làm việc bằng ước Caliburn, bạn cần một cấu trúc dự án đặc biệt như đã thấy ở đây (và giải thích there): enter image description here

Bây giờ tôi thách thức bạn để lấy mã này và tạo ra một ứng dụng mẫu nhỏ. Tạo Chế độ xem Login (mà Đăng nhập bằng Nút hoặc bất kỳ thứ gì) và tạo một Chế độ xem Content bằng Nút Đăng xuất bằng Phương thức Đăng nhập Thành công/Đăng xuất.

Điều này sẽ giải quyết vấn đề của bạn với tối thiểu Mã và lớp học. Hy vọng điều này sẽ hữu ích cho bạn.

+0

Tôi cũng quan tâm đến cách thức hoạt động của tính năng này. Trong ví dụ của bạn ShellViewMode là gì? Nó có nên là ShellViewModel hay có thể chỉ là một chuỗi? Ngoài ra aKzenT nói rằng cửa sổ đăng nhập đã tồn tại nên làm thế nào điều này có thể ảnh hưởng đến thiết kế của bạn? – Kioshiki

+0

ShellViewMode là lỗi đánh máy. Tất nhiên đây là một chuỗi chuyển thông tin ngữ cảnh đến trình quản lý cửa sổ. Bạn cũng có thể thiết lập bối cảnh này thành một enum, đó sẽ là một ý tưởng tốt. Đối với Cửa sổ đăng nhập hiện tại, hãy đặt xaml này vào Login.xaml và đặt Giao diện người dùng thành các Hành động hiện tại trong chế độ xemMô hình. Điều này có thể không phức tạp vì hầu hết thời gian Đăng nhập Hộp thoại chỉ đơn giản là nút Đăng nhập/Hủy với hộp văn bản tên người dùng/mật khẩu. Autorisation sau đó có thể được thực hiện bởi ShellViewModel hoặc mở rộng giao diện với một số delegate xác nhận để tách logic này và làm cho nó có thể thay đổi trong suốt thời gian chạy. –

+1

Tôi nghĩ rằng một chuỗi là đúng trong trường hợp này, như bạn nói một enum sẽ tốt hơn. Tôi nghĩ rằng bạn vẫn không có ý tưởng giống như tôi với cửa sổ đăng nhập hiện tại (mặc dù tôi có thể có ý tưởng sai).Tôi đang nghĩ về một tình huống mà bạn phải sử dụng một cửa sổ hiện có từ một hội đồng nhị phân, có thể trong một công ty họ có một cửa sổ WPF hoặc thậm chí một dạng WindowsForms đã được sử dụng cho quá trình đăng nhập. để xác thực, v.v.) Tôi nghĩ rằng sẽ làm cho nó khá khó khăn để tìm một giải pháp sạch sẽ. – Kioshiki

3

Tôi đã tạo một thứ gì đó về cơ bản nhưng có thể cần nhiều công việc hơn để có thể sử dụng được. Bạn có thể tìm thấy nhận xét và nguồn đầy đủ trên bài đăng này Caliburn.Micro Login Window sample trên trang web của tôi.

Tôi đã sử dụng IEventAggregator của Caliburn.Micro để kiểm soát quá trình chuyển đổi giữa hai cửa sổ. Bạn nhận được mã này để mở màn hình đăng nhập:

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

cùng một nguồn này được sử dụng cho cả lần đầu tiên ứng dụng mở và khi sự kiện Đăng xuất được xuất bản. sự kiện Thoát trông như thế này:

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

Khi đăng nhập thành công nó sử dụng mã này để mở cửa sổ chính mà là dựa trên một ViewModel:

ContentViewModel viewModel; 
viewModel = IoC.Get<ContentViewModel>(); 
viewModel.Username = e.Username; 
this.windowManager.ShowWindow(viewModel); 
Các vấn đề liên quan