2009-11-02 47 views
129

Tôi hiện đang làm việc với mẫu Microsoft MVVM và thấy thiếu các ví dụ chi tiết làm bực mình. Ví dụ ContactBook bao gồm cho thấy rất ít Command handling và ví dụ duy nhất tôi tìm thấy là từ một bài báo của tạp chí MSDN, nơi các khái niệm tương tự nhưng sử dụng một cách tiếp cận hơi khác và vẫn thiếu sự phức tạp. Có bất kỳ ví dụ MVVM phong nha mà ít nhất là hiển thị các hoạt động CRUD cơ bản và chuyển đổi thoại/nội dung không?Ví dụ hay về Mẫu MVVM


gợi ý của mọi người là thực sự hữu ích và tôi sẽ bắt đầu biên soạn một danh sách các nguồn tốt

Khung/Templates

bài viết hữu ích

Screencasts

Thư viện bổ sung

+0

Tôi rất vui vì những tài nguyên này đã hữu ích. Tôi hiện đang trong ứng dụng MVVM sản xuất thứ hai của mình và sẽ tiếp tục thêm nội dung sẽ hữu ích cho những người bắt đầu khi tôi bắt gặp nó. – jwarzech

Trả lời

54

Thật không may là không có ứng dụng ví dụ MVVM tuyệt vời nào làm mọi thứ và có rất nhiều cách tiếp cận khác nhau để thực hiện. Đầu tiên, bạn có thể muốn làm quen với một trong các khung ứng dụng (Prism là một lựa chọn tốt), bởi vì chúng cung cấp cho bạn các công cụ tiện lợi như tiêm phụ thuộc, chỉ huy, tập hợp sự kiện, v.v để dễ dàng thử các mẫu khác nhau phù hợp với bạn .

Việc phát hành lăng kính:
http://www.codeplex.com/CompositeWPF

Nó bao gồm một ứng dụng ví dụ khá phong nha (thương nhân cổ phiếu) cùng với rất nhiều ví dụ nhỏ hơn và làm thế nào để là. Ít nhất đó là một minh chứng tốt về một số mẫu phụ phổ biến mà mọi người sử dụng để làm cho MVVM thực sự hoạt động. Họ có những ví dụ cho cả CRUD và hộp thoại, tôi tin.

Lăng kính không nhất thiết cho mọi dự án, nhưng đó là điều tốt để làm quen.

CRUD: Phần này khá dễ dàng, các liên kết hai chiều của WPF giúp bạn dễ dàng chỉnh sửa hầu hết dữ liệu. Bí quyết thực sự là cung cấp một mô hình giúp dễ dàng thiết lập giao diện người dùng. Ít nhất bạn muốn đảm bảo rằng ViewModel của bạn (hoặc đối tượng nghiệp vụ) triển khai INotifyPropertyChanged để hỗ trợ ràng buộc và bạn có thể liên kết các thuộc tính trực tiếp với các điều khiển giao diện người dùng, nhưng bạn cũng có thể muốn thực hiện IDataErrorInfo để xác thực. Thông thường, nếu bạn sử dụng một số loại giải pháp ORM thiết lập CRUD là một snap.

Bài viết này chứng tỏ hoạt động crud đơn giản: http://dotnetslackers.com/articles/wpf/WPFDataBindingWithLINQ.aspx

Nó được xây dựng trên LinqToSql, nhưng đó là không liên quan đến ví dụ - tất cả những gì là quan trọng là đối tượng kinh doanh của bạn thực hiện INotifyPropertyChanged (mà lớp được tạo ra bởi LinqToSql làm) . MVVM không phải là điểm của ví dụ đó, nhưng tôi không nghĩ rằng nó quan trọng trong trường hợp này.

Bài viết này chứng tỏ xác nhận dữ liệu
http://blogs.msdn.com/wpfsdk/archive/2007/10/02/data-validation-in-3-5.aspx

Một lần nữa, hầu hết các giải pháp ORM tạo ra các lớp học đã thực hiện IDataErrorInfo và thường cung cấp một cơ chế để làm cho nó dễ dàng để thêm quy tắc xác nhận tùy chỉnh.

Hầu hết thời gian bạn có thể lấy một đối tượng (mô hình) được tạo bởi một số ORM và bọc nó trong một ViewModel chứa nó và lệnh lưu/xóa - và bạn đã sẵn sàng ràng buộc giao diện người dùng thẳng đến các thuộc tính của mô hình.

Quan điểm sẽ trông giống như một cái gì đó như thế này (ViewModel có một tài sản Item chứa mô hình, giống như một lớp được tạo ra trong ORM):

<StackPanel> 
    <StackPanel DataContext=Item> 
     <TextBox Text="{Binding FirstName, Mode=TwoWay, ValidatesOnDataErrors=True}" /> 
     <TextBox Text="{Binding LastName, Mode=TwoWay, ValidatesOnDataErrors=True}" /> 
    </StackPanel> 
    <Button Command="{Binding SaveCommand}" /> 
    <Button Command="{Binding CancelCommand}" /> 
</StackPanel> 

Dialogs: Dialogs và MVVM là một chút khôn lanh. Tôi thích sử dụng một hương vị của cách tiếp cận Mediator với hộp thoại, bạn có thể đọc thêm một chút về nó trong câu hỏi StackOverflow này:
WPF MVVM dialog example

cách tiếp cận thông thường của tôi, mà không phải là MVVM khá cổ điển, có thể được tóm tắt như sau:

Lớp cơ sở cho hộp thoại ViewModel hiển thị các lệnh cho cam kết và hủy tác vụ, một sự kiện để cho phép khung nhìn biết rằng hộp thoại đã sẵn sàng để đóng và bất kỳ thứ gì bạn cần trong tất cả các hộp thoại của bạn.

Chế độ xem chung cho hộp thoại của bạn - đây có thể là cửa sổ hoặc điều khiển loại lớp phủ "phương thức" tùy chỉnh. Trái tim của nó là người trình bày nội dung mà chúng ta đổ viewmodel vào, và nó xử lý hệ thống dây điện để đóng cửa sổ - ví dụ về thay đổi ngữ cảnh dữ liệu, bạn có thể kiểm tra xem ViewModel mới có được thừa kế từ lớp cơ sở của bạn không, và nếu có, đăng ký sự kiện đóng có liên quan (trình xử lý sẽ gán kết quả hộp thoại). Nếu bạn cung cấp chức năng đóng phổ quát thay thế (ví dụ như nút X), bạn nên đảm bảo chạy lệnh đóng tương ứng trên ViewModel.

Một nơi nào đó bạn cần cung cấp mẫu dữ liệu cho Chế độ xem của mình, chúng có thể rất đơn giản đặc biệt vì bạn có thể có chế độ xem cho mỗi hộp thoại được đóng gói trong điều khiển riêng. Các mẫu dữ liệu mặc định cho một ViewModel sau đó sẽ giống như thế này:

<DataTemplate DataType="{x:Type vmodels:AddressEditViewModel}> 
    <views:AddressEditView DataContext={Binding} /> 
</DataTemplate> 

Quan điểm thoại cần phải có quyền truy cập vào đó, bởi vì nếu không nó sẽ không biết làm thế nào để hiển thị các ViewModel, ngoài giao diện người dùng thoại chia sẻ nội dung của nó về cơ bản là:

<ContentControl Content={Binding} /> 

Mẫu dữ liệu tiềm ẩn sẽ ánh xạ chế độ xem cho mô hình, nhưng ai sẽ khởi chạy nó?

Đây là phần không phải là mvvm. Một cách để làm điều đó là sử dụng một sự kiện toàn cầu. Điều tôi nghĩ là tốt hơn nên làm là sử dụng thiết lập loại tập hợp sự kiện, được cung cấp thông qua việc tiêm phụ thuộc - theo cách này sự kiện là toàn cầu đối với vùng chứa chứ không phải toàn bộ ứng dụng. Prism sử dụng khuôn khổ thống nhất cho ngữ nghĩa container và tiêm phụ thuộc, và nói chung tôi thích Unity khá một chút.

Thông thường, có nghĩa là cửa sổ gốc đăng ký sự kiện này - nó có thể mở hộp thoại và đặt ngữ cảnh dữ liệu của nó thành ViewModel được truyền vào với sự kiện được nâng lên.

Thiết lập điều này theo cách này cho phép ViewModels yêu cầu ứng dụng mở hộp thoại và phản hồi hành động của người dùng ở đó mà không biết gì về giao diện người dùng vì vậy phần lớn MVVM-ness vẫn hoàn tất.

Tuy nhiên, đôi khi giao diện người dùng phải nâng cao hộp thoại, điều này có thể khiến mọi việc trở nên phức tạp hơn một chút. Hãy xem xét ví dụ, nếu vị trí hộp thoại phụ thuộc vào vị trí của nút mở nó.Trong trường hợp này, bạn cần có một số thông tin cụ thể về giao diện người dùng khi bạn yêu cầu mở hộp thoại. Tôi thường tạo một lớp riêng biệt chứa một ViewModel và một số thông tin giao diện người dùng có liên quan. Thật không may một số khớp nối dường như không thể tránh khỏi ở đó.

Pseudo code của một handler nút đó đặt ra một hộp thoại mà cần dữ liệu vị trí phần tử:

ButtonClickHandler(sender, args){ 
    var vm = DataContext as ISomeDialogProvider; // check for null 
    var ui_vm = new ViewModelContainer(); 
    // assign margin, width, or anything else that your custom dialog might require 
    ... 
    ui_vm.ViewModel = vm.SomeDialogViewModel; // or .GetSomeDialogViewModel() 
    // raise the dialog show event 
} 

Quan điểm hộp thoại sẽ liên kết với dữ liệu vị trí, và vượt qua các ViewModel chứa đến nội ContentControl. Bản thân ViewModel vẫn không biết gì về giao diện người dùng.

Nói chung, tôi không sử dụng thuộc tính trả về DialogResult của phương thức ShowDialog() hoặc mong đợi chuỗi chặn cho đến khi hộp thoại đóng. Một hộp thoại không chuẩn thường không hoạt động như thế, và trong một môi trường tổng hợp, bạn thường không thực sự muốn một trình xử lý sự kiện để chặn như thế nào. Tôi thích để cho ViewModels đối phó với điều này - người tạo ra một ViewModel có thể đăng ký các sự kiện liên quan của nó, thiết lập các phương thức commit/cancel, vv, vì vậy không cần phải dựa vào cơ chế UI này.

Vì vậy, thay vì quy trình này:

// in code behind 
var result = somedialog.ShowDialog(); 
if (result == ... 

tôi sử dụng:

// in view model 
var vm = new SomeDialogViewModel(); // child view model 
vm.CommitAction = delegate { this.DoSomething(vm); } // what happens on commit 
vm.CancelAction = delegate { this.DoNothing(vm); } // what happens on cancel/close (optional) 
// raise dialog request event on the container 

tôi thích nó theo cách này bởi vì hầu hết các hộp thoại của tôi đều là phòng không chặn kiểm soát giả phương thức và làm nó theo cách này có vẻ đơn giản hơn là làm việc xung quanh nó. Dễ dàng để kiểm tra đơn vị là tốt.

+0

Cảm ơn câu trả lời chi tiết! Gần đây tôi thấy rằng vấn đề lớn nhất của tôi là khi tôi cần có một giao tiếp MainViewModel với các mô hình khung nhìn khác để xử lý luồng của ứng dụng. Tuy nhiên có vẻ như MVVM + Mediator dường như là cách tiếp cận phổ biến. – jwarzech

+2

Người hòa giải chắc chắn giúp, mẫu kết hợp sự kiện (Prism có triển khai tốt) cũng thực sự hữu ích khi khớp nối thấp là mục tiêu. Ngoài ra, chế độ xem chính của bạn thường có chế độ xem con riêng của mình và không nên gặp sự cố khi liên lạc với họ. Bạn cần sử dụng trình hòa giải hoặc/và trình tổng hợp sự kiện khi các mô hình con của bạn cần tương tác với các mô-đun khác trong ứng dụng của bạn mà chúng không nhất thiết biết - bao gồm giao diện người dùng (ví dụ hộp thoại của tôi là về trường hợp cụ thể này). – Egor

+1

Hướng dẫn làm việc với hộp thoại và cửa sổ thực sự hữu ích. Tuy nhiên, tôi đang mắc kẹt với một vài vấn đề: 1. Làm thế nào để bạn thiết lập tiêu đề cửa sổ từ xem? 2. Làm cách nào để bạn xử lý cài đặt cửa sổ chủ sở hữu? – djskinner

2

Dự án mẫu trong Cinch framework cho thấy công cụ CRUD và chuyển hướng cơ bản. Đó là một ví dụ khá tốt về việc sử dụng MVVM và bao gồm một số multi-part article giải thích cách sử dụng và động lực của nó.

3

Bạn đã xem Caliburn chưa? Mẫu ContactManager có rất nhiều thứ tốt trong đó. Các mẫu WPF chung cũng cung cấp một cái nhìn tổng quan về các lệnh. Tài liệu này khá tốt và các diễn đàn đang hoạt động. Được đề xuất!

2

Tôi cũng chia sẻ trong sự thất vọng của bạn. Tôi đang viết một ứng dụng và tôi đã có những 3 yêu cầu:

  • Extensible
  • WPF với MVVM
  • ví dụ
  • GPL tương thích

Tất cả tôi thấy là bit và miếng, vì vậy tôi chỉ mới bắt đầu viết nó là tốt nhất tôi có thể. Sau khi tôi nhận được một chút, tôi nhận ra có thể có những người khác (như chính bạn), người có thể sử dụng một ứng dụng tham chiếu, vì vậy tôi đã tái cấu trúc các công cụ chung thành khung ứng dụng WPF/MVVM và phát hành nó dưới LGPL. Tôi đặt tên nó là SoapBox Core. Nếu bạn vào trang tải xuống, bạn sẽ thấy nó đi kèm với một ứng dụng demo nhỏ và mã nguồn cho ứng dụng demo đó cũng có sẵn để tải xuống. Hy vọng bạn thấy rằng hữu ích. Ngoài ra, gửi email cho tôi theo địa chỉ scott {at} soapboxautomation.com nếu bạn muốn biết thêm thông tin.

CHỈNH SỬA: Cũng đã đăng CodeProject article giải thích cách hoạt động.

6

Jason Dolinger đã thực hiện tốt screencast của MVVM. Giống như Egor đã đề cập, không có một ví dụ điển hình nào. Tất cả đều kết thúc. Hầu hết là những ví dụ MVVM tốt, nhưng không phải khi bạn gặp phải các vấn đề phức tạp. Mọi người đều có cách riêng của họ. Laurent Bugnion có một cách tốt để giao tiếp giữa viewmodels là tốt. http://blog.galasoft.ch/archive/2009/09/27/mvvm-light-toolkit-messenger-v2-beta.aspx Cinch cũng là một ví dụ điển hình. Paul Stovel có một số post tốt cũng giải thích rất nhiều với khung Magellan của mình.

1

Thậm chí tôi đã chia sẻ sự thất vọng cho đến khi tôi đưa vấn đề vào tay tôi. Tôi bắt đầu IncEditor.

IncEditor (http://inceditor.codeplex.com) là một trình soạn thảo cố gắng giới thiệu nhà phát triển cho WPF, MVVM & MEF. Tôi bắt đầu nó và quản lý để có được một số chức năng như hỗ trợ 'chủ đề'. Tôi không có chuyên gia trong WPF hoặc MVVM hoặc MEF vì vậy tôi không thể đặt rất nhiều chức năng trong đó. Tôi thực hiện một yêu cầu chân thành cho các bạn để làm cho nó tốt hơn để những cái cửa sổ như tôi có thể hiểu nó tốt hơn.

1

Ở đây tôi thêm liên kết của một ứng dụng WPF (Quản lý hàng tồn kho App) mà sử dụng kiến ​​trúc MVVM thiết kế bởi tôi.

Giao diện người dùng của nó thật tuyệt vời. https://github.com/shivam01990/InventoryManagement

0

Tôi đã viết một ví dụ đơn giản MVVM từ đầu trên dự án mã ở đây là liên kết MVVM WPF step by step. Nó bắt đầu từ một kiến ​​trúc 3 lớp đơn giản và tốt nghiệp bạn sử dụng một số khung như PRISM.

enter image description here