2010-03-29 37 views
12

Tôi đang sử dụng MVVM trong ứng dụng WPF. Tôi rất mới cho cả hai. Hãy để tôi nói rằng tôi không thuần khiết trong mô hình MVVM, tôi đang cố gắng sử dụng nhiều thực hành tốt nhất có thể nhưng tôi đang cố gắng làm cho những gì tôi nghĩ là thỏa hiệp hợp lý để làm cho nó hoạt động trong môi trường của chúng tôi. Ví dụ, tôi không cố gắng để đạt được 0% mã trong codebehind View của tôi.MVVM Xem tham chiếu tới ViewModel

Tôi có một số câu hỏi về các phương pháp hay nhất.

1) Tôi hiểu rằng tôi không muốn máy ảo của mình biết về Chế độ xem được đính kèm, nhưng có hợp lý để Chế độ xem có tham chiếu đến máy ảo của nó không?

2) Nếu điều khiển trong Chế độ xem mở ra Chế độ xem khác (chẳng hạn như hộp thoại), tôi có nên xử lý điều này trong Chế độ xem không? Có vẻ như sai khi xử lý nó trong VM kể từ đó VM có một số kiến ​​thức về một View cụ thể.

+0

Chế độ xem tham chiếu đến máy ảo nhưng không được theo cách khác. http://stackoverflow.com/a/3670669/1977871 – VivekDev

Trả lời

10

1) Chế độ xem chắc chắn có liên quan đến ViewModel thông qua DataContext. Và bạn được phép truyền DataContext trong Chế độ xem của mình:

public class ShellView : Window 
{ 
    … 
    public ShellViewModel { get { return DataContext as ShellViewModel; } } 

Điều này không vi phạm với mẫu Chế độ xem-ViewModel.

.

2) Bạn đã đúng. ViewModel không được mở Chế độ xem khác. Một cách tiếp cận tốt hơn là sử dụng Bộ điều khiển. Họ chịu trách nhiệm về quy trình làm việc của một ứng dụng.

Nếu bạn quan tâm đến thông tin chi tiết hơn thì bạn có thể xem WPF Application Framework (WAF).

+0

+1 Để mở rộng lời giải thích của jbe cho # 2 một chút, bạn có thể hiển thị một lệnh trên VM được kết nối tới trình xử lý lệnh của bộ điều khiển sẽ xử lý hiển thị khung nhìn thứ hai. Ngoài WAF, bạn cũng có thể xem Thư viện ứng dụng tổng hợp của nhóm P & P (hay còn gọi là Prism): http://compositewpf.codeplex.com/Wikipage –

+0

Vâng, rõ ràng là View biết về VM thông qua DataContext, tôi đoán là tôi đã không thấy rằng kể từ khi tất cả các ràng buộc dữ liệu trong xaml của tôi là quá phụ thuộc vào máy ảo mà có một tham chiếu mạnh mẽ hơn để nó trong codebehind Views của tôi hầu như không có vẻ giống như một điều xấu. Và cảm ơn cho tip trên bộ điều khiển, tôi sẽ nhìn vào mô hình đó. – BrettRobi

+0

'Mô hình ShellViewModel công khai {get {return DataContext như ShellViewModel; }} ' –

2

1). Khung nhìn sẽ cần một tham chiếu đến mô hình khung nhìn ở một mức nào đó, vì khung nhìn sẽ hoạt động như là khung dữ liệu của khung nhìn.

2) Một cách để xử lý này là phải có một viewmodel khái quát hóa đại diện cho một hộp thoại, đó là thuộc sở hữu của viewmodel chính (một trong những được sử dụng như các quan điểm DataContext.)

Bạn có thể sử dụng một lệnh để thùng một thể hiện mới của khung nhìn hộp thoại, sẽ có bảng dữ liệu tương ứng được xác định trong tài nguyên của bạn. Mẫu này sẽ được thiết lập để liên kết với kiểu dialogviewmodel.

+0

+1 nhưng tôi nghĩ rằng đối với điểm 1), OP đã hỏi liệu nó có phù hợp với lớp View để biết về lớp ViewModel chính xác, thay vì chỉ liên kết trên một datacontext của loại không xác định thông qua tên thuộc tính. –

+0

Mỗi Wim, thực sự tôi đã đề cập đến lớp View có một tham chiếu đến ViewModel, không chỉ thông qua databinding (mà là trừu tượng). – BrettRobi

+0

Vào điểm # 2. Tôi đang sử dụng bộ công cụ Ánh sáng MVVM mà tôi tạo Chế độ xem, sau đó liên kết với một ViewModel thông qua dịch vụ Định vị. Vì vậy, tôi không tạo VM, vì họ không biết cách đính kèm một View cho chính họ. Vì vậy, có vẻ như tôi cần một cách để tạo ra các Xem hộp thoại, và nơi mà nên xảy ra (Xem hoặc VM)? – BrettRobi

3

1) Dưới đây là hai cách thực hành đơn giản cho Chế độ xem "biết" của Chế độ xem. Đó là hợp lý cho một View để biết về một ViewModel (cho Data Binding) - nhưng bạn có thể không cần nó trong trường hợp của bạn. Xem liệu một trong các phương pháp này có giúp giải quyết vấn đề của bạn hay không. Có nhiều cách khác, nhưng những nên đơn giản đủ:

public View(ViewModel vm) 
{ 
    View.DataContext = vm; 
} 

public Bootstrapper(View v, ViewModel vm) 
{ 
    v.DataContext = vm; 
    //or, if you want it to have no parameters 
    View v = new View(); 
    ViewModel vm = new ViewModel(); 
    v.DataContext = vm; 
} 

Tùy chọn đầu tiên không phải là xấu nếu bạn có một công cụ vị trí dịch vụ, nhưng có một hương vị của MVVM rằng không giống như bất kỳ mã trong View's Code-Behind. Lựa chọn thứ hai không phải là xấu, hoặc, nên đơn giản, đủ cho nhiệm vụ của bạn.

2.) Câu hỏi này có thể là một điểm dính trong thiết kế MVVM. Nếu chúng ta đang nói về một MessageBox Win32 chung, tôi sẽ thường tách logic đó thành một đối tượng bổ sung và đặt nó trong máy ảo. Bằng cách này có xu hướng rõ ràng hơn một chút. (Ví dụ, tôi đã chọn một mục trong ListBox, tôi đã đính kèm một Xóa ICommand vào hành động đó, và trong ViewModel của tôi khi ICommand này được thực thi, tôi sẽ ping MessageBoxObject của mình để hỏi xem người dùng có muốn xóa nó không mục). Các hộp thoại "nâng cao" hơn sẽ sử dụng ViewModels và DataTemplates bổ sung cho các ViewModels đó. Tôi thích cách tiếp cận Mediator.

+0

Cảm ơn, phản hồi được đánh giá cao – BrettRobi

1

Build Your Own MVVM Framework

Tôi tìm thấy phương pháp được đề xuất bởi Rob Eisenberg rất thú vị.

Những điểm mấu chốt:

ước
  1. qua cấu hình
  2. ViewModel đầu tiên

Đó là rất giống với triết lý ASP.NET MVC.

Tôi đặc biệt khuyên bạn nên xem video.

2

Khá muộn, nhưng tôi nghĩ điều này đủ khó để xứng đáng với nhiều góc độ khác nhau.


Tôi hiểu rằng tôi không muốn VM của tôi để biết về các Xem đính kèm, nhưng là nó hợp lý cho Xem để có một tài liệu tham khảo để VM của nó?

Như đã trả lời, sắp xếp ViewModel thích hợp liên quan đến ViewModel được chỉ định làm thuộc tính DataContext của Chế độ xem. Điều đó cho phép DataBindings được "automagically" thành lập từ XAML khai báo, hoặc tinh chỉnh thông qua mã phía sau.

Đôi khi, bạn sẽ bị cám dỗ để viết, trong mã của bạn phía sau, một cái gì đó như thế này:

var dc = DataContext as CleverViewModel; 
CleverViewModel.CleverProperty.Add(someValue); // just a simple example 

Tôi tin rằng cách thích hợp để đạt được điều này sắp xếp những thứ không phải là để đúc DataContext, nhưng thay vào đó:

  1. có một số kiểm soát chuyên dụng trong View, ví dụ một ItemsControl với ItemsSource hai chiều databound của nó đối với một số tài sản trong viewmodel:

    <ItemsSource x:Name="cleverControl" Visibility="Collapsed" ItemsSource="{Binding CleverProperty, Mode=TwoWay}"/>

  2. Cast thuộc tính ràng buộc thay vì toàn bộ ViewModel, trong mã đằng sau:

    var collection = (ObservableCollection<double>)cleverControl.ItemsSource; collection.Add(someValue);

Lưu ý sự khác biệt quan trọng: Cách tiếp cận thứ hai trong ví dụ này không yêu cầu Xem để biết loại ViewModel, nó chỉ cần một tài sản có tên CleverProperty của loại ObservableCollection<double>. Điều này cho phép tôi có chế độ ViewModels đa hình hoặc thậm chí là kiểu vịt.


Nếu một điều khiển trong một Xem mở một View (chẳng hạn như một hộp thoại) nên tôi xử lý này trong View? Có vẻ như sai khi xử lý nó trong VM từ thì VM có một số kiến ​​thức về một Chế độ xem cụ thể.

Điều này không nên xảy ra trong MVVM nghiêm ngặt và không khó tránh sử dụng DataTemplates.DataTemplates ánh xạ một loại nhất định của DataContext để một loại nhất định của xem, do đó bất cứ lúc nào các DataContext của một thay đổi ContentControl, màn hình của nó cũng thay đổi, với điều kiện bạn có một DataTemplate cho loại đó:

  1. Một điều khiển trong giao diện có thể gửi một lệnh tới ViewModel, do đó sẽ cập nhật một số thuộc tính của riêng nó, điều này sẽ được phản ánh theo chế độ xem.

  2. Chế độ xem có thể chứa một Chế độ xem khác, ngoài kiến ​​thức về Chế độ xem. Trong trường hợp này, mã phía sau có thể thao tác dữ liệu văn bản của chế độ xem được chứa.

Có nhiều sự tinh tế hơn, nhưng tôi đã sử dụng phương pháp này với kết quả tốt. Hy vọng điều này sẽ giúp một ai đó.

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