2009-09-27 32 views
46

Bất kỳ ai đi qua một cách thông minh để đóng chế độ xem trong chế độ xem bằng MVVM?WPF (MVVM): Đóng chế độ xem từ ViewModel?

Có thể có cách sử dụng ràng buộc để báo hiệu chế độ xem (cửa sổ) đóng?

Tôi thực sự đánh giá cao mọi đầu vào bất kỳ ai có. Về cơ bản tôi có một loginView mà là ràng buộc với một loginViewModel, trong viewmodel (sử dụng ràng buộc trên một lệnh) tôi kiểm tra để xem nếu đăng nhập thành công và nếu nó là tôi về cơ bản tải lên một View mới (mainview) và gắn DataContext của nó ...

nhưng tôi vẫn có thể hiện loginView - vì vậy tôi cần phải báo hiệu nó để dỡ bỏ ..

tôi cũng đã hy vọng cho một giải pháp chung chung, vì tôi chắc chắn rằng tôi đang đi cần để làm điều này trong các tình huống khác

Bất kỳ ý tưởng nào?

Trả lời

35

Chỉnh sửa: Xem my blog post để có giải thích chi tiết hơn.

Khi tôi cần đạt được điều đó, tôi sử dụng giao diện IRequestCloseViewModel mà tôi đã tạo.

Giao diện này chỉ chứa một sự kiện: RequestClose. Sự kiện này được nâng lên bởi ViewModel (được kế thừa từ lớp ViewModelBase AND triển khai IRequestCloseViewModel) khi nó muốn đóng chế độ xem được kết hợp của nó.

Trong ứng dụng của tôi, tất cả Cửa sổ kế thừa từ lớp trừu tượng ApplicationWindow. Lớp trừu tượng này được thông báo mỗi lần DataContext thay đổi và trong trình xử lý kiểm tra nếu DataContext hỗ trợ IRequestCloseViewModel. Nếu đúng như vậy, trình xử lý sự kiện được thiết lập để đóng cửa sổ khi sự kiện được kích hoạt.

Ngoài ra, giống như Kent cho biết, bạn có thể sử dụng bộ điều khiển màn hình xử lý mecanism này trong một lớp bên ngoài.

+0

Hi Jalfp, âm thanh này thực sự tuyệt vời, Bạn có một ví dụ về lớp trừu tượng mà tôi cần tất cả các cửa sổ để kế thừa từ? .. Nếu bạn có một ví dụ bao gồm Irquestcloseviewmodel cũng - nó sẽ là tuyệt vời –

+0

Tôi sẽ đưa một bài viết trên blog của tôi trong vài giờ tới. Tôi sẽ cho bạn biết ngay sau khi trực tuyến :-) – japf

+0

Đây là: http://www.japf.fr/2009/09/how-to-close-a-view-from-a-viewmodel/ Hy vọng sự trợ giúp này :) – japf

8

Nói chung, bạn sẽ sử dụng một số loại bộ điều khiển/trình dẫn/dịch vụ để kích hoạt kích hoạt/hủy kích hoạt màn hình. MVVM không có nghĩa là Một Mẫu để Quy tắc Tất cả. Bạn sẽ cần phải kết hợp nó với các mẫu khác trong bất kỳ ứng dụng không tầm thường nào.

Điều đó nói rằng, trong một số trường hợp có ý nghĩa để có một mô hình xem quản lý vòng đời của các mô hình xem trẻ em. Ví dụ: bạn có thể có một số EditorViewModel quản lý tập hợp các kiểu xem con - một cho mỗi tài liệu đang được chỉnh sửa. Trong trường hợp đó, chỉ cần thêm/xóa/từ bộ sưu tập này có thể dẫn đến kích hoạt chế độ xem/hủy kích hoạt. Nhưng điều này không có vẻ như nó phù hợp với trường hợp sử dụng của bạn.

2

Tôi sẽ sử dụng ApplicationController để khởi tạo LoginViewModel và hiển thị LoginView. Khi người dùng tiến hành với màn hình đăng nhập, ApplicationController sẽ đóng cửa sổ LoginView và hiển thị MainView với MainViewModel của nó.

Cách thực hiện việc này có thể được hiển thị trong các ứng dụng mẫu của dự án WPF Application Framework (WAF).

4

Bạn có thể tạo lệnh đính kèm vào cửa sổ và khi thực hiện đóng cửa sổ. Sau đó, bạn có thể liên kết lệnh đó với một thuộc tính trên mô hình khung nhìn của bạn và thực hiện lệnh khi bạn muốn đóng cửa sổ.

+0

Đẹp và đơn giản. – Darren

22

Không chắc những gì khuôn khổ MVVM bạn đang sử dụng, nhưng hầu hết chứa một số loại giải pháp tin nhắn/thông báo đó là dễ dàng có những thứ đăng ký cho các tin nhắn được gửi đi. Không có lý do gì mà tôi có thể tưởng tượng rằng chế độ xem của bạn không thể đăng ký một thông báo như "CloseWindowsBoundTo" và viewModel là người gửi. Sau đó, trong quan điểm của bạn, bạn chỉ có thể đăng ký cho tin nhắn đó, và so sánh dữ liệu hiện tại của bạn với người gửi. Nếu chúng khớp nhau, hãy đóng cửa sổ lại.

Đơn giản và giữ cho chế độ xem của bạn được trừu tượng hóa từ chế độ xem.

Dưới đây sẽ là cách tiếp cận của tôi sử dụng bộ công cụ MVVM-ánh sáng:

Trong ViewModel:

public void notifyWindowToClose() 
{ 
    Messenger.Default.Send<NotificationMessage>(
     new NotificationMessage(this, "CloseWindowsBoundToMe") 
    ); 
} 

Và trong Xem:

Messenger.Default.Register<NotificationMessage>(this, (nm) => 
{ 
    if (nm.Notification == "CloseWindowsBoundToMe") 
    { 
     if (nm.Sender == this.DataContext) 
      this.Close(); 
    } 
}); 
+0

Chỉ cần tự hỏi, nếu nó có thể gây ra rò rỉ bộ nhớ bởi vì bạn vượt qua một liên kết đến một đối tượng mà phải được xử lý? .. –

2

Câu trả lời này cho thấy một cách khác để làm điều này :

How should the ViewModel close the form?

Nó sử dụng thuộc tính đính kèm để liên kết thuộc tính cửa sổ DialogResult với thuộc tính ViewModel. Khi đặt giá trị của DialogResult thành true hoặc false, khung nhìn được đóng lại.

2

Chỉ cần đóng một EventHandler theo mã phía sau và xử lý mọi thứ khác trong mô hình chế độ xem nơi bạn có thể sử dụng lệnh ràng buộc.

+0

Tôi sẽ bị tấn công bởi một tia sét ViewModel hình để làm điều này, và không viết của riêng tôi IRequestCloseViewMô hình giao diện? – Ted

7

Tôi biết đây là một câu hỏi cũ, nhưng tôi có một cách tốt để làm điều này vì vậy tôi nghĩ rằng tôi muốn chia sẻ cho bất cứ ai khác tình cờ gặp điều này. Tôi đã từng sử dụng hành vi của trình soạn thảo kèm theo, nhưng tôi thấy giải pháp bên dưới dễ dàng hơn nơi tôi có thể sử dụng nó. Mẫu dưới đây lấy ví dụ về nút đóng trên cửa sổ để đơn giản.

chuyển cửa sổ làm tham số lệnh.

trong nút XAML cho quan điểm:

CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" 

trong lệnh thực hiện phương pháp trong mô hình điểm:

if (parameter is System.Windows.Window) 
{ 
    (parameter as System.Windows.Window).Close(); 
} 
0

Để đóng nhìn từ viewmodel i dùng Toolkit Galasoft MVVM nhẹ mà bạn có thể tải xuống tại đây: http://www.mvvmlight.net/

  1. tạo một lớp như sau: lớp công khai ClosingRequested: MessageBase {}

  2. thêm điều này vào trình xem của bạn: Messenger.Default.Register (this, vm, msg => Close());

  3. gọi này để đóng cửa sổ của bạn: Messenger.Default.Send (new ClosingRequested(), this);

0

Bạn cũng có thể thực hiện việc này bằng sự kiện.Mặc dù bạn cần như 3 dòng mã trong mã xem của bạn phía sau (một số thuần túy MVVM không thích điều này);

Trong viewmodel của bạn, bạn tạo một sự kiện quan điểm có thể đăng ký:

public event CloseEventHandler Closing; 
    public delegate void CloseEventHandler(); 
    private void RaiseClose() 
    { 
     if (Closing != null) 
      Closing(); 
    } 

Trong bạn, xem bạn đăng ký cho sự kiện này sau khi phương thức InitializeComponent của bạn như sau:

 public View 
     { 
      *//The event can be put in an interface to avoid direct dependence of the view on the viewmodel. So below becomes 
      //ICloseView model = (ICloseView)this.DataContext;* 
      ProgressWindowViewModel model = (ProgressWindowViewModel)this.DataContext; 
      model.Closing += Model_Closing; 
     } 
     private void Model_Closing() 
     { 
      this.Close(); 
     } 

Bạn chỉ cần gọi RaiseClose() khi bạn đã sẵn sàng đóng View từ ViewModel.

Bạn thậm chí có thể sử dụng phương pháp này để gửi tin nhắn đến chế độ xem từ chế độ xem.

Sự kiện có thể được đặt trong giao diện để tránh sự phụ thuộc trực tiếp vào chế độ xem trên chế độ xem.

Các vấn đề liên quan