2012-12-12 25 views
7

Ví dụ về ứng dụng WPF MVVM Tôi đã thấy trên Internet xem VM là một lớp tương tác với một lớp dịch vụ sử dụng sự kiện "cũ" từ thư viện bên ngoài hoặc tương tác với web bằng cách sử dụng HTTP hoặc bất cứ điều gì. Nhưng nếu tôi xây dựng tất cả M, V, VM, dịch vụ và các phần khác thì sao? Làm thế nào để xây dựng tương tác đúng giữa lớp dịch vụ và lớp viewmodel? Tôi có thể chỉ cần đặt ObservableCollection<OrderModel> vào dịch vụ và trả lại từ chế độ xem cho chế độ xem hay được coi là phương pháp xấu và có lựa chọn thay thế tốt hơn không?Quan sátCollection trong lớp dịch vụ của ứng dụng WPV MVVM

Trả lời

6

Bạn có thể làm điều này - tất nhiên bạn có thể. Lý do chính để làm một điều như vậy là giảm trùng lặp trên nhiều ứng dụng WPF.

Tuy nhiên, một thách thức bạn có thể gặp phải trong một số trường hợp, tùy thuộc vào triển khai lớp dịch vụ/lớp dữ liệu của bạn, là các dịch vụ chạy lâu mà lần lượt sử dụng kết nối cơ sở dữ liệu. ObservableCollections hấp dẫn từ quan điểm của việc có lớp dịch vụ tự động đồng bộ hóa các thay đổi được thực hiện bởi một ứng dụng đến một kho dữ liệu; tuy nhiên nó trở nên phức tạp khi bạn muốn giao tiếp các thay đổi bắt nguồn từ chính dữ liệu (tức là để đáp lại một số quy trình khác tạo/sửa đổi dữ liệu).

Lớp dịch vụ không thể thay thế bản sao (ví dụ trong trường hợp thay đổi quy mô lớn), vì nó không còn là chủ sở hữu duy nhất của tham chiếu nữa - nhưng ngay cả khi có thể phá vỡ bất kỳ ràng buộc nào của giao diện người dùng đối với bộ sưu tập.

Vì vậy, bạn cố gắng giữ cho phiên bản được cập nhật. Nếu các dịch vụ của bạn bị ràng buộc vào một cơ sở dữ liệu, thì trừ khi bạn mã hóa một số quy trình giám sát dài hạn trong dịch vụ của bạn, cách đơn giản duy nhất để giữ một ObservableCollection được cập nhật sau khi nó được loại bỏ sẽ là giữ các kết nối cơ sở dữ liệu/bối cảnh (trong trường hợp của LINQ to Sql hoặc EF) mở - bởi vì các đối tượng liên quan khác vv sẽ không thể phục hồi được (trừ khi bạn buộc tất cả các đối tượng được đọc trong một lần - không thể mở rộng). Được rồi, do đó, có thể viết một số hình thức lớp quản lý có thể quản lý các kết nối cho bạn - nhưng ngoài việc bỏ phiếu không thể tránh khỏi hoặc có thể thông báo SQL Server mà bạn có thể sử dụng, tôi tin rằng mã có thể khá phức tạp .

Điều đó nói rằng, nó thực sự phụ thuộc - vấn đề cụ thể là một vấn đề cần tìm, nhưng có thể bạn có một kiến ​​trúc và môi trường trong đó những thứ như vậy không quan trọng.

Lời khuyên của tôi, nếu bạn muốn thử - hãy tiếp tục. Cho tôi? Tôi đã nghĩ về nó - và ngoài việc thêm INotifyPropertyChanged vào một số mô hình miền, tôi gắn bó với ý tưởng rằng một ứng dụng có VM riêng của nó. Nhiều ứng dụng có thể chia sẻ cùng một máy ảo - nhưng điều đó sẽ không nằm trong chính lớp dịch vụ.

Lớp dịch vụ cung cấp quyền truy cập vào dữ liệu và logic nghiệp vụ theo cách thông thường một lần. Các lớp trong mô hình VM có tuổi thọ dài hơn nhiều - và cố gắng mã hóa một lớp dịch vụ lâu dài nổi tiếng là rất khó thực hiện - đặc biệt nếu bạn muốn nó thử và giải quyết tất cả các vấn đề mà tất cả các ứng dụng trong tương lai có thể trình bày. Chắc chắn bạn sẽ kết thúc các dịch vụ mã hóa hoặc các loại máy ảo trong lớp dịch vụ cho một ứng dụng duy nhất - trong trường hợp đó nó có thể cũng đã đi vào trong codebase của ứng dụng đó.

0

Tôi sẽ không làm điều đó vì một số lý do. Chúng được ghi lại ở đây: Common mistakes with an observable collection

Tác giả trải qua một số sai lầm mà mọi người mắc phải, bao gồm cả việc sử dụng chúng trong lớp dịch vụ.

+0

Bài viết nói trong phần "Sử dụng nó trong mô hình" sử dụng OC trong mô hình là xấu, nhưng tôi đã thấy nhiều ví dụ khi mô hình được đưa vào dạng xem, không có chuyển đổi. Một trong những khuyến nghị là: "Nếu một mô hình thực hiện INotifyPropertyChanged, hãy sử dụng nó; nếu không, hãy chuyển đổi nó". Vì vậy, sử dụng các bộ sưu tập quan sát trong các mô hình không được coi là một thực hành tồi của mọi người ... Dù sao, câu hỏi là: cách thay thế, đúng cách là gì? – Athari

+0

Tôi tin rằng cách thay thế (đúng cách) là sử dụng IEnumerable. Giống như @PeteH được đề xuất, hãy thử sử dụng OC càng nhiều càng tốt, còn được gọi là trong ViewModel của bạn. Và viết một lớp CollectionViewModel để lộ ra ObservableCollection của ViewModels như một thuộc tính, với các đăng ký OnCollectionChanged, v.v. – Heliac

2

Tôi chỉ muốn sử dụng ObservableCollection từ điểm mà tại đó khía cạnh "quan sát" có liên quan, thường là VM phơi bày điều gì đó với V. Tiếp tục xuống ngăn xếp (ví dụ: M) bị cám dỗ để gắn bó với những thứ chung chung hơn như danh sách và bộ sưu tập (trừ khi bạn đặc biệt cần cho những thứ khác). Nó đủ dễ dàng cho máy ảo để tạo ra một ObservableCollection dựa trên bất kỳ IEnumerable cũ trong mọi trường hợp.

Một câu hỏi hợp lý, đặc biệt là vị trí của ObservableCollection trong không gian tên System.Collections dường như gợi ý rằng Microsoft không đặc biệt nghĩ về điều này như một lớp chuyên biệt (và chắc chắn không phải là wpf-specific).

+0

Vấn đề gắn bó với các danh sách và số đếm "truyền thống" là tôi vẫn cần cập nhật khung nhìn thông qua viewmodel khi có thứ gì đó được thêm vào danh sách; do đó, viewmodel cần được thông báo về một mục mới của dịch vụ. Nếu tôi thêm các sự kiện, nó sẽ trông giống như một bộ sưu tập có thể quan sát (và có thể bị lỗi) ... – Athari

+0

@Athari Tôi có thể thấy bạn đến từ đâu - chắc chắn không có ý nghĩa gì khi bạn thực hiện ObservableCollection của riêng bạn. Nhìn xa hơn ngăn xếp, làm thế nào dịch vụ sẽ biết rằng mọi thứ đã thay đổi? – PeteH

+0

@Athari - Đó chính xác là những gì tôi làm. Khi tôi thêm một mục mới theo chương trình (tức là không sử dụng dòng mới DataGrid, nhưng thêm một thực thể), tôi có một sự kiện OnEntityAdded mà tôi ném từ phương thức Tạo trong Kho lưu trữ của mình: ** OnEntityAdded (new ModelEntityAddedEventArgs (entity)) ** . Như bạn có thể thấy, thực thể được chuyển trong các đối số sự kiện. Lớp dịch vụ của tôi đăng ký sự kiện này. – Heliac

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