Giới thiệu
Trong MVVM, cách thực hành thông thường là để các View tìm thấy các ViewModels của chúng bằng cách phân giải chúng từ vùng chứa phụ thuộc (DI). Điều này xảy ra tự động khi vùng chứa được yêu cầu cung cấp (giải quyết) một thể hiện của lớp View. Vùng chứa đưa ViewModel vào View bằng cách gọi một hàm tạo của View chấp nhận tham số ViewModel; lược đồ này được gọi là nghịch đảo điều khiển (IoC).
Lợi ích của DI
Lợi ích chính ở đây là vùng chứa có thể được định cấu hình tại thời điểm chạy với hướng dẫn về cách giải quyết các loại mà chúng tôi yêu cầu từ nó. Điều này cho phép khả năng kiểm tra cao hơn bằng cách hướng dẫn nó giải quyết các loại (Chế độ xem và Mô hình xem) mà chúng tôi sử dụng khi ứng dụng của chúng tôi thực sự chạy, nhưng hướng dẫn nó khác khi chạy các bài kiểm tra đơn vị cho ứng dụng. Trong trường hợp thứ hai, ứng dụng thậm chí sẽ không có giao diện người dùng (nó không chạy; chỉ là các bài kiểm tra) vì vậy vùng chứa sẽ giải quyết các mô phỏng thay cho các loại "bình thường" được sử dụng khi ứng dụng chạy.
Các vấn đề bắt nguồn từ DI
Cho đến nay, chúng tôi đã thấy rằng phương pháp DI cho phép dễ dàng kiểm tra ứng dụng bằng cách thêm một lớp trừu tượng lên trên việc tạo các thành phần ứng dụng. Có một vấn đề với cách tiếp cận này: nó không hoạt động tốt với các nhà thiết kế trực quan như Microsoft Expression Blend.
Vấn đề là trong cả chạy ứng dụng bình thường và chạy thử nghiệm đơn vị, ai đó phải thiết lập vùng chứa với hướng dẫn về những loại cần giải quyết; ngoài ra, ai đó phải yêu cầu vùng chứa phân giải Chế độ xem để các Mô hình xem có thể được đưa vào chúng.
Tuy nhiên, trong thời gian thiết kế không có mã của chúng tôi đang chạy . Nhà thiết kế cố gắng sử dụng phản chiếu để tạo các bản sao của Chế độ xem của chúng tôi, có nghĩa là:
- Nếu phương thức khởi tạo View yêu cầu thể hiện ViewModel, nhà thiết kế sẽ không thể khởi tạo View - nó sẽ xảy ra lỗi theo một số cách được kiểm soát
- Nếu Chế độ xem có một hàm tạo không tham số thì Chế độ xem sẽ được khởi tạo, nhưng nó
DataContext
sẽ null
như vậy, vì vậy chúng ta sẽ nhận được một chế độ xem "trống" trong trình thiết kế - điều này không hữu ích lắm
Nhập ViewModelLocator
ViewModelLocator là một phần trừu tượng bổ sung được sử dụng như sau:
- Bản thân View khởi tạo ViewModelLocator như một phần tài nguyên của nó và liên kết dữ liệu DataContext của nó với thuộc tính ViewModel của bộ định vị
- Bộ định vị bằng cách nào đó phát hiện nếu chúng ta đang ở chế độ thiết kế
- Nếu không ở chế độ thiết kế, bộ định vị trả về một ViewModel mà nó phân giải từ vùng chứa DI, như đã giải thích ở trên
- Nếu ở chế độ thiết kế, bộ định vị trả về một ViewModel "giả" cố định bằng cách sử dụng logic riêng của nó (hãy nhớ: không có vùng chứa trong thời gian thiết kế!); ViewModel này thường đi kèm với dữ liệu giả
Tất nhiên, điều này có nghĩa là View phải có một hàm tạo không tham số để bắt đầu (nếu không nhà thiết kế sẽ không thể khởi tạo nó).
Tóm lược
ViewModelLocator là một thành ngữ cho phép bạn giữ lợi ích của DI trong ứng dụng MVVM của mình đồng thời cho phép mã của bạn hoạt động tốt với các nhà thiết kế trực quan. Điều này đôi khi được gọi là "khả năng hòa trộn" của ứng dụng của bạn (đề cập đến Expression Blend).
Sau khi hiểu rõ những điều trên, hãy xem một ví dụ thực tế tại đây .
Cuối cùng, sử dụng các mẫu dữ liệu không phải là một giải pháp thay thế cho việc sử dụng ViewModelLocator, mà là một giải pháp thay thế cho việc sử dụng các cặp View / ViewModel rõ ràng cho các phần của giao diện người dùng của bạn. Thông thường, bạn có thể thấy rằng không cần xác định Chế độ xem cho Mô hình xem vì bạn có thể sử dụng mẫu dữ liệu thay thế.