Các khái niệm cơ bản về MVVM— ViewModel nên làm gì?


83

Cố gắng nắm bắt các khái niệm về MVVM, tôi đã đọc một số blog và xem một vài dự án.

Theo những gì tôi hiểu, một Chế độ xem thật ngu ngốc, nó chỉ biết cách trình bày một cái gì đó được chuyển cho nó.

Mô hình chỉ là dữ liệu thuần túy và ViewModel là thứ hoạt động giống như một phần đệm ở giữa hai mô hình, nó sẽ lấy thông tin từ Mô hình và chuyển nó vào Chế độ xemChế độ xem phải biết cách trình bày thông tin đó. Hoặc ngược lại, nếu thông tin trong Chế độ xem thay đổi, nó sẽ chuyển thay đổi đó sang Mô hình .

Nhưng tôi vẫn chưa biết cách áp dụng khái niệm này. Ai đó có thể giải thích một kịch bản rất đơn giản để tôi có thể nắm bắt được khái niệm không? Tôi đã xem xét một số dự án, nhưng nó vẫn không có ý nghĩa hoàn toàn, vì vậy nếu ai đó có thể viết nó ra bằng tiếng Anh đơn giản, điều đó thật tuyệt.


2
Không thể đồng ý với tuyên bố rằng quan điểm "chỉ biết làm thế nào để trình bày một cái gì đó được chuyển cho nó.". View lấy dữ liệu từ VM. Không ai chuyển dữ liệu cho nó. Không ai biết về quan điểm. Đây là một sự khác biệt quan trọng so với MVP. Trong MVP (bạn có thể nghĩ về nó như về một ứng dụng WPF đơn giản với logic phía sau, nó là một mẫu MVP) thì codebehind là người trình bày truyền dữ liệu đến View như bạn đã nói.
Grigory

Câu trả lời:


146

Tôi thích nghĩ về nó theo cách này:

Các lượt xem, như bạn nói, thật ngu ngốc. Josh Smith, nhà văn của bài báo MSDN nổi tiếng và thường được liên kết trên MVVM, đã nói rằng lượt xem là "trang phục mà dữ liệu mặc." Các khung nhìn không bao giờ thực sự chứa dữ liệu hoặc thao tác trực tiếp với nó, chúng chỉ bị ràng buộc với các thuộc tính và lệnh của các mô hình xem của bạn.

Mô hình là các đối tượng mô hình hóa miền ứng dụng của bạn , như trong các đối tượng kinh doanh. Ứng dụng của bạn có phải là một cửa hàng âm nhạc không? Có lẽ đối tượng mô hình của bạn sẽ là nghệ sĩ, album và bài hát. Ứng dụng của bạn có phải là trình duyệt biểu đồ tổ chức không? Có lẽ đối tượng mô hình của bạn sẽ là người quản lý và nhân viên. Các đối tượng mô hình này không liên quan đến bất kỳ loại kết xuất trực quan nào và thậm chí chúng không liên quan trực tiếp đến ứng dụng bạn đang đưa chúng vào - các đối tượng mô hình của bạn phải hoàn toàn có ý nghĩa như một họ các đối tượng đại diện cho một số loại của miền. Lớp mô hình cũng thường bao gồm những thứ như bộ truy cập dịch vụ.

Điều này đưa chúng ta đến Viewmodels. Họ là ai? Chúng là những đối tượng mô hình hóa ứng dụng GUI, nghĩa là chúng cung cấp dữ liệu và chức năng để các lượt xem sử dụng. Chúng là những gì xác định cấu trúc và hành vi của ứng dụng thực tế mà bạn đang xây dựng. Đối với các đối tượng mô hình, miền là bất kỳ miền nào bạn chọn (cửa hàng nhạc, trình duyệt biểu đồ tổ chức, v.v.), nhưng đối với mô hình xem, miền là một ứng dụng đồ họa. Các mô hình xem của bạn sẽ đóng gói hành vi và dữ liệu của mọi thứ mà ứng dụng của bạn thực hiện. Chúng sẽ hiển thị các đối tượng và danh sách dưới dạng thuộc tính, cũng như những thứ như Lệnh. Một lệnh chỉ là một hành vi (đơn giản nhất là một cuộc gọi phương thức) được gói gọn trong một đối tượng mang nó - ý tưởng này rất quan trọng bởi vì các khung nhìn được điều khiển bởi databinding, gắn các điều khiển trực quan vào các đối tượng. Trong MVVM, bạn không cung cấp cho một nút là phương thức xử lý Nhấp chuột,

Đối với tôi, những điều khó hiểu nhất là:

  • Mặc dù các mô hình xem là mô hình của một ứng dụng đồ họa, chúng không tham chiếu trực tiếp hoặc sử dụng các khái niệm trực quan. Ví dụ: bạn không muốn tham chiếu đến các điều khiển Windows trong ViewModels của mình - những thứ đó sẽ xuất hiện trong chế độ xem. ViewModels chỉ đơn giản là hiển thị dữ liệu và hành vi cho các điều khiển hoặc các đối tượng khác sẽ liên kết với chúng. Ví dụ - bạn có một dạng xem với ListBox trong đó không? Viewmodel của bạn gần như chắc chắn sẽ có một số loại bộ sưu tập trong đó. Chế độ xem của bạn có nút không? Khung nhìn của bạn gần như chắc chắn sẽ có một số lệnh trong đó.
  • Có một số loại đối tượng có thể được coi là "mô hình khung nhìn". Loại mô hình xem đơn giản nhất để hiểu là loại mô hình trực tiếp đại diện cho điều khiển hoặc màn hình trong mối quan hệ 1: 1, như trong "màn hình XYZ có một hộp văn bản, một hộp danh sách và ba nút, vì vậy mô hình xem cần một chuỗi, một tập hợp, và ba lệnh. " Một loại đối tượng khác phù hợp với lớp viewmodel là một lớp bao bọc xung quanh đối tượng mô hình để cung cấp cho nó hành vi và làm cho nó dễ sử dụng hơn đối với một chế độ xem - đây là nơi bạn đi vào khái niệm về các lớp view model "dày" và "mỏng". Lớp mô hình xem "mỏng" là một tập hợp các mô hình xem hiển thị các đối tượng mô hình của bạn trực tiếp với các khung nhìn, có nghĩa là các khung nhìn sẽ liên kết trực tiếp với các thuộc tính trên các đối tượng mô hình. Điều này có thể hoạt động đối với những thứ như chế độ xem đơn giản, chỉ đọc, nhưng nếu bạn muốn có hành vi liên kết với từng đối tượng? Bạn không muốn điều đó trong mô hình, bởi vì mô hình không liên quan đến ứng dụng, nó chỉ liên quan đến miền của bạn. Bạn có thể đặt nó vào một đối tượng bao bọc đối tượng mô hình của bạn và cung cấp dữ liệu và hành vi thân thiện với ràng buộc hơn. Đối tượng trình bao bọc này cũng được coi là một mô hình xem, và việc có chúng dẫn đến một lớp mô hình xem "dày hơn", nơi các chế độ xem của bạn không bao giờ kết thúc trực tiếp với bất kỳ thứ gì trên một lớp mô hình. Bộ sưu tập sẽ chứa các mô hình xem bao bọc các mô hình thay vì chỉ chứa các mô hình. Bạn có thể đặt nó vào một đối tượng bao bọc đối tượng mô hình của bạn và cung cấp dữ liệu và hành vi thân thiện với ràng buộc hơn. Đối tượng trình bao bọc này cũng được coi là một mô hình xem và việc có chúng dẫn đến một lớp mô hình xem "dày hơn", nơi các chế độ xem của bạn không bao giờ kết thúc trực tiếp với bất kỳ thứ gì trên một lớp mô hình. Bộ sưu tập sẽ chứa các mô hình xem bao bọc các mô hình thay vì chỉ chứa các mô hình. Bạn có thể đặt nó vào một đối tượng bao bọc đối tượng mô hình của bạn và cung cấp dữ liệu và hành vi thân thiện với ràng buộc hơn. Đối tượng trình bao bọc này cũng được coi là một mô hình xem, và việc có chúng dẫn đến một lớp mô hình xem "dày hơn", nơi các chế độ xem của bạn không bao giờ kết thúc trực tiếp với bất kỳ thứ gì trên một lớp mô hình. Bộ sưu tập sẽ chứa các mô hình xem bao bọc các mô hình thay vì chỉ chứa các mô hình.

Lỗ hổng sâu hơn - có rất nhiều thành ngữ để tìm ra như ValueConverters giúp MVVM hoạt động và có rất nhiều điều để áp dụng khi bạn bắt đầu nghĩ về những thứ như Blendability, thử nghiệm và cách truyền dữ liệu xung quanh ứng dụng của bạn và đảm bảo rằng mỗi viewmodel có quyền truy cập vào hành vi mà nó cần (đây là nơi đưa vào phụ thuộc), nhưng hy vọng phần trên là một khởi đầu tốt. Điều quan trọng là nghĩ về hình ảnh của bạn, miền của bạn và cấu trúc và hành vi của ứng dụng thực tế của bạn như ba điều khác nhau.


3
+1 - Tôi đã kết thúc ở đây vì tôi bị nhầm lẫn bởi ViewModel "trình bao bọc" gặp phải trong một số mã mẫu. Cám ơn giải thích rõ ràng cho tôi :-)
Riegardt Steyn

1
Câu trả lời tuyệt vời - ước gì tôi có thể +10.
Nick Hodges

1
@nlawalker Rất tuyệt vời! Đôi chút mà bạn nhận xét ở trên đã khiến tôi bối rối trong một thời gian dài. Nhiều bài báo và blog chỉ nói về "các tính năng chính" của MVVM, nhưng khi bạn cố gắng làm quen với nó, mọi thứ bắt đầu rất phức tạp ! Chẳng hạn như "Làm thế nào để điều hướng các Chế độ xem đó?" "Mức độ chi tiết thích hợp khi chúng tôi thiết kế ViewModels là gì?" "Một Chế độ xem phải có một ViewModel phù hợp hay một ViewModel có thể được sử dụng lại trong các Chế độ xem khác nhau không?" Việc bạn làm rõ về ViewModel được tạo bằng "Slim VM" và "Thick VM" thực sự có ý nghĩa! Tôi đang thử nó, nó hoạt động tốt nên xa! :)
Vuốt

@nlawalker Cảm ơn! Và một câu hỏi khác: tôi có treeView và tạo TreeViewViewModel. Vì vậy, nếu tôi tạo các phương thức như: ExpandTree () tại ViewModel của mình. Nó có đúng cách không?
user2545071

Wow, đây là một bài báo xuất sắc, khá tốt công việc @nlawalker
Vivek Shukla

25

Sử dụng bài viết cực kỳ hữu ích này làm nguồn, đây là bản tóm tắt cho View , ViewModelModel .


Lượt xem:

  • Dạng xem là một phần tử trực quan, chẳng hạn như cửa sổ, trang, điều khiển của người dùng hoặc mẫu dữ liệu. Dạng xem xác định các điều khiển có trong dạng xem và bố cục và kiểu dáng trực quan của chúng.

  • Chế độ xem tham chiếu đến mô hình chế độ xem thông qua thuộc tính của nó DataContext. Các điều khiển trong dạng xem là dữ liệu liên kết với các thuộc tính và lệnh được hiển thị bởi mô hình dạng xem.

  • Chế độ xem có thể tùy chỉnh hành vi liên kết dữ liệu giữa chế độ xem và mô hình chế độ xem. Ví dụ: chế độ xem có thể sử dụng bộ chuyển đổi giá trị để định dạng dữ liệu được hiển thị trong giao diện người dùng hoặc nó có thể sử dụng các quy tắc xác thực để cung cấp xác thực dữ liệu đầu vào bổ sung cho người dùng.

  • Chế độ xem xác định và xử lý hành vi trực quan của giao diện người dùng, chẳng hạn như hoạt ảnh hoặc chuyển đổi có thể được kích hoạt từ sự thay đổi trạng thái trong mô hình chế độ xem hoặc thông qua tương tác của người dùng với giao diện người dùng.

  • Mã phía sau của chế độ xem có thể xác định logic giao diện người dùng để triển khai hành vi trực quan khó thể hiện trong XAML hoặc yêu cầu tham chiếu trực tiếp đến các điều khiển giao diện người dùng cụ thể được xác định trong chế độ xem.

LƯU Ý:
Vì mô hình chế độ xem không được có kiến ​​thức rõ ràng về các phần tử hình ảnh cụ thể trong chế độ xem, mã để thao tác lập trình các phần tử hình ảnh trong chế độ xem phải nằm trong mã phía sau của chế độ xem hoặc được đóng gói trong một hành vi.


Xem mô hình:

  • Mô hình khung nhìn là một lớp không trực quan và không bắt nguồn từ bất kỳ lớp cơ sở WPF hoặc Silverlight nào. Nó đóng gói logic trình bày cần thiết để hỗ trợ ca sử dụng hoặc tác vụ người dùng trong ứng dụng. Mô hình khung nhìn có thể kiểm tra độc lập với khung nhìn và mô hình.

  • Mô hình dạng xem thường không tham chiếu trực tiếp dạng xem. Nó thực hiện các thuộc tính và lệnh mà khung nhìn có thể liên kết dữ liệu. Nó thông báo cho chế độ xem về bất kỳ thay đổi trạng thái nào thông qua các sự kiện thông báo thay đổi qua giao diện INotifyPropertyChangedINotifyCollectionChanged.

  • Mô hình khung nhìn điều phối sự tương tác của khung nhìn với mô hình. Nó có thể chuyển đổi hoặc thao tác dữ liệu để chế độ xem có thể dễ dàng sử dụng và có thể triển khai các thuộc tính bổ sung có thể không có trên mô hình. Nó cũng có thể thực hiện xác thực dữ liệu thông qua IDataErrorInfohoặc các INotifyDataErrorInfogiao diện.

  • Mô hình khung nhìn có thể xác định các trạng thái lôgic mà khung nhìn có thể đại diện cho người dùng một cách trực quan.

LƯU Ý:
Bất kỳ điều gì quan trọng đối với hành vi logic của ứng dụng đều phải đi vào mô hình khung nhìn. Mã để truy xuất hoặc thao tác các mục dữ liệu sẽ được hiển thị trong chế độ xem thông qua liên kết dữ liệu phải nằm trong mô hình chế độ xem.


Mô hình:

  • Các lớp mô hình là các lớp không trực quan đóng gói dữ liệu của ứng dụng và logic nghiệp vụ. Họ chịu trách nhiệm quản lý dữ liệu của ứng dụng và đảm bảo tính nhất quán và tính hợp lệ của nó bằng cách đóng gói các quy tắc nghiệp vụ bắt buộc và logic xác thực dữ liệu.

  • Các lớp mô hình không tham chiếu trực tiếp đến khung nhìn hoặc các lớp mô hình xem và không phụ thuộc vào cách chúng được triển khai.

  • Các lớp mô hình thường cung cấp các sự kiện thông báo thay đổi thuộc tính và bộ sưu tập thông qua các giao diện INotifyPropertyChangedINotifyCollectionChanged. Điều này cho phép chúng dễ dàng bị ràng buộc dữ liệu trong chế độ xem. Các lớp mô hình đại diện cho các tập hợp các đối tượng thường dẫn xuất từ ObservableCollection<T>lớp.

  • Các lớp mô hình thường cung cấp xác nhận dữ liệu và báo cáo lỗi thông qua một trong hai IDataErrorInfohoặc INotifyDataErrorInfogiao diện.

  • Các lớp mô hình thường được sử dụng cùng với một dịch vụ hoặc kho lưu trữ đóng gói truy cập dữ liệu và bộ nhớ đệm.


17

Tôi đã viết điều này bằng "tiếng Anh đơn giản" như tôi có thể nghĩ trong loạt bài này trên MVVM . Đặc biệt, sơ đồ này có thể là cách giải thích ngắn gọn, đơn giản nhất.

Nói như vậy, về cơ bản, "mô hình" là dữ liệu hoặc quy tắc kinh doanh của bạn. Nó thực sự không nên biết về cách thức hoặc nơi nó sẽ được sử dụng, và đặc biệt là không biết công nghệ nào sẽ sử dụng nó. "Model" là phần lõi của ứng dụng - và không cần phải lo lắng về việc ứng dụng có phải là WPF, Silverlight, Windows Forms, ASP.NET, v.v. hay không - nó chỉ là "chính nó" ở dạng thuần túy.

"View" là phần hoàn toàn dành riêng cho công nghệ. Trong MVVM, lý tưởng là Chế độ xem phải là XAML gần 100%, vì điều này mang lại một số lợi ích lớn về tính linh hoạt.

Tuy nhiên, cần phải có thứ gì đó chuyển thông tin từ Mô hình sang một dạng nào đó mà công nghệ có thể sử dụng được - đây là lúc ViewModel phát huy tác dụng. Ví dụ: điều này thường "kết hợp" các lớp mô hình thành một "ViewModel" cho dữ liệu cụ thể đó bao gồm Lệnh (để chạy logic), thực hiện INotifyPropertyChanged(để hỗ trợ liên kết dữ liệu), v.v. Chính nó - nó là cầu nối tạo nên Mô hình có thể sử dụng được bởi View.


Được rồi cảm ơn. Tôi nghĩ về Mô hình là các đối tượng và ViewModel là các phương pháp xử lý các đối tượng, sao cho một khung nhìn có thể hiểu được các "đối tượng" của Mô hình. Nhưng tôi đã được thông báo rằng điều này là sai, bản thân ViewModel cũng là các đối tượng. Tôi đoán đây là điều thực sự làm tôi bối rối.
RKM

@Rosie: Tôi khuyên bạn nên đọc (hoặc ít nhất là đọc lướt) qua bộ truyện mà tôi đã trích dẫn. Tôi đã viết nó đặc biệt bởi vì có rất ít (hầu như không có) bài viết về MVVM không đã giả sử bạn hiểu MVC hoặc MVP, vv Đó là thực sự là một "từng bước" chuyển tiếp;)
Reed Copsey

Nhận ra đây là luồng zombie một chút ... Sơ đồ của bạn cho biết rằng máy ảo chứa "Trạng thái và logic dành riêng cho ứng dụng " (my emph). Điều đó có gợi ý rằng bạn nghĩ rằng máy ảo có thể / nên chứa logic QA dữ liệu không? RssWpfMVVM.csproj có liên quan dường như không có bất kỳ QA rõ ràng nào trong hai mô hình xem của nó.
ruffin

1

Bạn có thể tìm thấy phần giới thiệu tuyệt vời về MVVM trong video của Jason Dolinger tại đây . Tôi đã giữ video bên mình khá lâu khi bắt đầu, nó thực sự hữu ích.


1
Liên kết đã chết
ibrahim mahrir 20/02/19

1
@ibrahimmahrir ~ Tôi đã cập nhật liên kết đến một URL đang hoạt động. Tôi đang tải video xuống.
InteXX

0

Việc xây dựng một ViewModel thể hiện một mặt tiền nhất quán trên Mô hình bên dưới có thể phức tạp hơn rất nhiều so với vẻ ngoài của nó. Bài viết này về cách xây dựng các đối tượng ViewModel trình bày cách xây dựng một ViewModel và minh họa một số vấn đề bạn có thể gặp phải - cùng với những giải pháp có vẻ như là hợp lý. Khi tôi đọc nó, phần về xử lý bộ sưu tập bị thiếu, nhưng nó vẫn có một số điểm thú vị.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.