Tuesday , 19 March 2024
HOT

Mô hình MVVM (Model – View – ViewModel)

I. Introduction
Mục đích của bài viết này nhằm giới thiệu về MVVM patern (Model – View – ViewModel). Những nội dung trong bài này được tổng hợp lại từ 2 bài viết trên codeproject (xem thêm tại phần tham khảo). Nói sơ qua một chút về pattern này, MVVM thường được sử dụng trong lập trình các ứng dụng WPF và Silverlight, nó cho phép chúng ta dễ dàng thay đổi giao diện (GUI) của ứng dụng mà không cần phải thay đổi code quá nhiều. Việc triển khai MVVM cho project thực sự đơn giản hơn nhiều so với những gì mà người ta tưởng tưởng về nó.

II. Background
Tại sao bạn nên sử dụng Model – View – ViewModel pattern? Thực tế việc sử dụng pattern này trong quá trình phát triển các ứng dụng WPF hoặc Silverlight mang lại cho developer nhiều lợi ích, có thể kể đến như sự tương tác hiệu quả giữa designer và developer, khả năng sử dụng lại các component hay việc thay đổi giao diện chương trình mà không cần thiết phải viết lại code quá nhiều…
Có một vài đánh giá sai lầm về MVVM đại loại như: “MVVM chỉ thích hợp với các project có giao diện phức tạp”, hay “MVVM sẽ làm phình to kích thước cũng như chi phí đối với các ứng dụng nhỏ”. Và một nhận xét nữa về đó là: “MVVM không cân bằng (scale)”. Theo ý kiến chủ quan thì những nhận xét như thế này chỉ phù hợp khi nói đến cách thức cài đặt cũng như kiến thức về MVVM của developer chứ không phải bản thân của MVVM pattern. Nói cách khác, nếu bạn mất hàng giờ đồng hồ để triển khai MVVM, điều đó có nghĩa là bạn đang thực hiện sai phương pháp. 


III. MVVM
MVVM là viết tắt của Model –View – ViewModel. Hình ảnh dưới đây sẽ mô tả về mối quan hệ giữa các thành phần trong pattern này.

model view viewmodel

1. Model

Trong thế giới lập trình, model đại diện cho các dữ liệu, thông tin mà chúng ta cần thao tác. Một ví dụ về model đó là contact (thông tin liên lạc), nó sẽ bao gồm tên, số điện thoại, địa chỉ, … Đơn vị của Model chính là Class. Như vậy xét ví dụ về model contact, chúng ta sẽ có class Contact, hay một ví dụ khác như class Customer dùng để lưu trữ thông tin về khách hàng, class Supplier lưu trữ các thông tin về các nhà cung cấp… Các class trong Model của MVVM đều giống như các class bình thường khác, chúng đều có một số các phương thức, properties… hay khả năng tự động lưu dữ liệu của nó và cơ sở dữ liệu.
Tuy nhiên cần phải lưu ý đó là model chỉ lưu giữ thông tin mà thôi, nó không quan tâm đến các hoạt động hay dịch vụ có thể thay đổi, điều khiển các thông tin đó. Ví dụ như nó không có trách nhiệm phải định dạng đoạn văn bản hiển thị như thế nào, hay làm sao để lấy một danh sách các item về từ remote server.

2. ViewModel

ViewModel là class định nghĩa cách dữ liệu tương tác với người dùng thông qua view. Nói cách khác ViewModel là model của View.
Một lưu ý quan trọng đó là ViewModel không mô tả giao diện sẽ trông như thế nào. Nó chỉ mô tả cách mà view hoạt động và thông tin nào sẽ được cung cấp cho người dùng.
Vấn đề cần bàn luận ở đây là, liệu ViewModel sẽ ảnh hưởng như thế nào đến phần hiển thị của View, ví dụ như việc xác định nội dung của một label, bạn sẽ sử dụng View hay ViewModel? Theo tôi, điều này tùy thuộc hoàn toàn vào đối tượng cũng như dự án mà bạn đang làm. Đôi khi label đó sẽ có nội dung do ViewModel quy định (bởi vì bạn cần thay đổi nội dung của label tùy theo sự kiện xảy ra), hay có khi designer sẽ quyết định label sẽ hiển thị như thế nào. Nói chung, nếu nó không phụ thuộc vào cơ sở dữ liệu thì nó sẽ thuộc về thẩm quyền của designer – tức là được định nghĩa trong View chứ không phải ViewModel.
Một ví dụ cụ thể về ViewModel như sau: giả sử boss của bạn yêu cầu rằng “Chúng ta cần phải hiển thị các thông tin chi tiết của người dùng ra bên ngoài, đồng thời cho phép họ thay đổi các thông tin đó”.
Như các bạn thấy, ông chủ của chúng ta không hề quy định bất cứ chi tiết nào về việc tên của người dùng phải được viết bằng font Tahoma Bold, phải sử dụng listbox hay combobox để hiển thị danh sách các user. Yêu cầu trên chính là định nghĩa về chức năng cũng như các dữ liệu cần thiết cho class CustomerEditViewModel. Phân tích kĩ hơn, dữ liệu yêu cầu ở đây chính là Customer và chức năng của nó là khả năng hiển thị và thay đổi nội dung các thuộc tính của Customer class. 
Tuy nhiên, chúng ta không muốn View lại biết và thao tác trực tiếp với các thông tin của Model (trong trường hợp này là class Customer). Do đó, bạn có thể xem ViewModel như là một thông dịch viên – nó dùng một đối tượng Customer và thực hiện việc chuyển đổi từ dữ liệu trong class này để hiển thị chính xác trong View


3. View
View là thành phần duy nhất mà người dùng có thể tương tác được trong chương trình, nó chính là thành phần mô tả dữ liệu. Trong WPF, view là một UserControl, lưu ý mặc dù View chính là UserControl nhưng không nhất thiết UserControl phải làView.
Vậy làm thế nào để phân biệt được? Rất đơn giản. Ban đầu bạn khởi tạo class ViewModel trước, như vậy bạn đã cóViewModel để quản lí các chức năng cần thiết, việc cuối cùng là tạo class View nhằm cho phép người dùng sử dụng các chức năng đó. Nếu một tính năng hiển thị nào đó nằm trên view và là một phần của ViewModel đã được khai báo trước đó, nhưng lại không có ViewModel của riêng nó thì đó đơn thuần chỉ là một UserControl.
Ví dụ, trong class CustomerEditViewModel mô tả ở trên, địa chỉ của khách hàng sẽ được hiển thị và có thể thay đổi được bởi người dùng. Ta có thể đưa việc hiển thị và thay đổi nội dung vào trong cùng một UserControl duy nhất, tuy nhiên UserControlnày sẽ sử dụng data source từ class CustomerEditViewModel chứ không phải là class CustomerAddressViewModel hayAddressViewModel.
Có một nhận định sai lầm trong MVVM đó là developer không nên viết thêm bất kì đoạn code nào trong phần code behind củaView (file view.xaml.cs). Tuy nhiên bạn cần hiểu chính xác về vấn đề này đó là developer nên tránh viết vào file code behind của view những đoạn code hoàn toàn không liên quan hay ảnh hưởng đến giao diện của chương trình.
Mặc dù không nên nhưng đôi khi nếu việc viết code behind tiện lợi hơn so với việc viết mã XAML thì sử dụng C# cũng không phải là ý kiến tồi. Ví dụ bạn muốn bind Command property của Button vào một đối tượng ICommand trong ViewModel của View, bạn có thể thực hiện điều này bằng XAML rất đơn giản và ngắn gọn. Tuy nhiên nếu bạn muốn xử lí sự kiện MouseOver của Button này thì sao? Chắc chắn bạn cũng có thể thực hiện được với XAML với các Storyboard, behaviours… tuy nhiên tại sao lại không viết code trong code-behind để xử lí sự kiện này bằng cách gọi Command tương ứng trong ViewModel?

Con tiep

Theo donetviet

Leave a Reply

Your email address will not be published. Required fields are marked *

*