2012-02-14 29 views
5

Trong ứng dụng WPF của tôi, tôi sử dụng mẫu MVVM cùng với tiêm phụ thuộc.Dữ liệu cũ trong Mô hình Chế độ xem MVVM với phụ thuộc tiêm

Chế độ xemMô hình chuẩn bị dữ liệu từ cơ sở dữ liệu lấy kho lưu trữ được chèn vào hàm tạo. Chúng cũng cư trú các thuộc tính với dữ liệu từ kho lưu trữ trong hàm tạo.

Chế độ xem tất cả được tạo trong hàm tạo tĩnh của lớp ViewModelLocator mà tất cả các Chế độ xem sử dụng để liên kết với ViewModel của chúng.

này có những nhược điểm sau:

  1. Dữ liệu trong Views là không bao giờ được cập nhật, không phải ngay cả khi đóng cửa và tái mở chúng, vì dụ ViewModel luôn là như nhau.
  2. Khi mở chế độ xem đầu tiên, tất cả Chế độ xem được khởi tạo và dữ liệu mà chúng yêu cầu được tải từ cơ sở dữ liệu.

tôi có thể nghĩ đến hai cách để giải quyết những vấn đề này:

  1. Làm cho mỗi ViewModel thực hiện một phương pháp mà đọc dữ liệu từ cơ sở dữ liệu và khởi tạo các thuộc tính - thay vì làm như vậy trong các nhà xây dựng. Điều này sẽ yêu cầu gọi phương thức đó mỗi khi một khung nhìn được mở ra. Điều này giới thiệu temporal coupling mà tôi không thích.
  2. Triển khai ViewModelLocator theo cách sao cho nó tạo ViewModel được yêu cầu mỗi khi thuộc tính tương ứng trên ViewModelLocator được gọi. Tôi không thích phương pháp này, bởi vì gốc bố cục của tôi sẽ không được thực thi khi bắt đầu chương trình nhưng sẽ lan truyền trong suốt thời gian hoạt động của chương trình.

Có cách nào khác để giải quyết vấn đề này không? Những người khác giải quyết vấn đề này như thế nào?

Trả lời

2

Thực hiện ViewModelLocator theo cách như vậy mà nó tạo ra yêu cầu ViewModel mỗi lần tài sản tương ứng trên ViewModelLocator được gọi.

Đây là cách tiếp cận khác mà tôi thường thực hiện trong các tình huống như thế này. Tuy nhiên, thay vì có ViewModelLocator được tạo ra thông qua DI của ViewModels, tôi soạn các nhà máy tạo ra ViewModel.

Tôi không thích phương pháp này, vì gốc bố cục của tôi sẽ không được thực thi khi bắt đầu chương trình nhưng sẽ được trải rộng trong suốt thời gian hoạt động của chương trình.

Điều này được "giải quyết", ít nhất một phần, bằng cách soạn thành phần soạn thảo các nhà máy thay vì chính các loại đó. Các thành phần xảy ra một lần khi khởi động, nhưng việc tạo ra có thể xảy ra bất kỳ lúc nào của ViewModel được đề cập.

Ví dụ, sử dụng MEF, bạn có thể chuyển nhập của bạn xung quanh để sử dụng ExportFactory<T> thay vì loại của chúng trực tiếp. Cùng với NonShared Creation Policy, bạn có thể tạo Mô hình Chế độ xem, nếu cần và luôn làm việc với dữ liệu mới, không có sự cố ghép nối thời gian.

+0

Cảm ơn câu trả lời của bạn. Có một nhà máy cho mỗi ViewModels của tôi có vẻ là một chút quá mức cần thiết vì các nhà máy sẽ chỉ được sử dụng ở một nơi và hiện không cần thiết. Hơn nữa họ không làm bất cứ điều gì khác hơn 'container.Resolve' sẽ làm. Vì ViewModelLocator vẫn sẽ là nơi duy nhất mà container sẽ được sử dụng, tôi thích gọi 'container.Resolve' hơn các nhà máy trừu tượng, bởi vì ngay cả trong trường hợp này, thùng chứa sẽ không bị rò rỉ vào mã ứng dụng. Lợi thế duy nhất của các nhà máy trừu tượng mà tôi có thể nghĩ đến là một lỗi ngay lập tức khi bắt đầu (tiếp theo) –

+0

(tiếp theo) nếu cấu hình của vùng chứa sẽ không chính xác. –

0

Lớp trừu tượng ViewModelBase lớp cơ sở của tôi yêu cầu phương thức AbstractDataCore() trừu tượng. Phương thức này có thể được gọi bằng tay bằng cách gọi Refresh() trên cá thể ViewModel hoặc bằng cách thiết lập cờ IsDirty. Khi ViewModel.IsVisible là true và IsDirty được thiết lập Refresh() cũng sẽ được gọi.

Bằng cách này, bạn có thể làm mới dữ liệu lười biếng bất cứ khi nào mô hình chế độ xem của bạn hiển thị và bạn cũng có thể gọi làm mới theo cách thủ công bằng cách gọi Làm mới().

Ví dụ bên dưới. (Tôi đã để lại thông báo INPC ra vì đơn giản)

public abstract class ViewModelBase 
{ 
    //Pull your data from the repository here 
    protected abstract void RefreshCore(); 
    public void Refresh() 
    { 
      RefreshCore(); 
      IsDirty = false; 
    } 

    private bool _isVisible = false; 
    //DataBind this to the visibility of element "hosting" your view model 
    public bool IsVisible 
    { 
     get { return _isVisible; } 
     set 
     { 
       if (_isVisible == value) 
        return; 


       _isVisible = value; 
       if (IsVisible && IsDirty) 
        Refresh(); 
     } 
    } 

    private bool _isDirty = true; 
    public bool IsDirty 
    { 
     get { return _isDirty; } 
     set 
     { 
      if (_isDirty == value) 
       return; 

      _isDirty = value; 
      if (IsVisible && IsDirty) 
       Refresh(); 
     } 
    } 

} 
+1

Làm thế nào để bạn giải quyết vấn đề khớp nối thời gian? Bạn chỉ sống với nó, và luôn luôn gọi làm mới khi cần thiết? –

+0

Tôi có một ApplicationViewModel định kỳ kiểm tra trạng thái của dữ liệu và thiết lập các cờ IsDirty thích hợp (nhưng chỉ các mô hình hiển thị xem mới được chủ động làm mới) Vì lý do hiệu suất, ApplicationViewModel cũng chứa bộ nhớ cache dữ liệu cục bộ mà các phiên bản ViewModelBase khác đọc từ trong các phương thức RefreshDataCore() của chúng. Bạn hoàn toàn linh hoạt để thực hiện điều này như bạn cần mặc dù – cordialgerm

+0

Cảm ơn câu trả lời của bạn. Tuy nhiên, tôi không thấy khớp nối thời gian được giải quyết, vì vậy đó không phải là những gì tôi sẽ sử dụng. –

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