2009-03-17 28 views
9

Tôi có ứng dụng MVVM. Trong một trong các ViewModels là 'FindFilesCommand' để điền vào một ObservableCollection. Sau đó tôi thực hiện một 'RemoveFilesCommand' trong cùng ViewModel. Lệnh này sau đó sẽ trả về một cửa sổ để nhận thêm một số đầu vào của người dùng.Nơi tốt nhất để hiển thị cửa sổ mới trong Chế độ xem mô hình ViewModel

Đâu là cách tốt nhất để làm điều này trong khi vẫn giữ nguyên mô hình MVVM? Bằng cách nào đó làm:

new WhateverWindow().Show()

trong ViewModel có vẻ sai.

Chúc mừng,

Steve

+0

Tôi đã trả lời một câu hỏi rất giống nhau trong [bài đăng này] (http://stackoverflow.com/a/15512972/385995). –

Trả lời

2

Cá nhân tôi xem kịch bản này là trường hợp mô hình xem cửa sổ chính muốn hiển thị tác vụ cho người dùng cuối hoàn tất.

Nó phải chịu trách nhiệm tạo nhiệm vụ và khởi tạo tác vụ đó. Khung nhìn nên chịu trách nhiệm tạo và hiển thị cửa sổ con và sử dụng tác vụ làm mô hình khung nhìn của cửa sổ mới được tạo ra.

Nhiệm vụ có thể bị hủy hoặc cam kết. Nó đưa ra một thông báo khi nó được hoàn thành.

Cửa sổ sử dụng thông báo để tự đóng. Mô hình chế độ xem gốc sử dụng thông báo để thực hiện công việc bổ sung sau khi tác vụ đã thực hiện nếu có công việc tiếp theo.

Tôi tin rằng điều này gần với điều tự nhiên/trực quan mà người dùng thực hiện với phương pháp tiếp cận mã của họ, nhưng được cấu trúc lại để tách mối quan hệ độc lập với UI thành mô hình chế độ xem mà không giới thiệu thêm chi phí khái niệm như dịch vụ, v.v.

Tôi thực hiện việc này cho Silverlight. Xem http://www.nikhilk.net/ViewModel-Dialogs-Task-Pattern.aspx để biết thêm chi tiết ... Tôi rất muốn nghe ý kiến ​​/ đề xuất thêm về điều này.

-1

Đối Dialogs thuộc loại này. Tôi định nghĩa nó như là một lớp lồng nhau của FindFilesCommand. Nếu hộp thoại cơ bản được sử dụng trong nhiều lệnh, tôi định nghĩa nó trong một mô-đun có thể truy cập vào các lệnh đó và có lệnh cấu hình hộp thoại cho phù hợp.

Các đối tượng lệnh đủ để hiển thị cách hộp thoại tương tác với phần còn lại của phần mềm. Trong phần mềm của riêng tôi, các đối tượng Command nằm trong các thư viện riêng của chúng để hộp thoại được ẩn khỏi phần còn lại của hệ thống.

Để làm bất kỳ điều gì thì ý kiến ​​của bạn là quá mức cần thiết. Ngoài ra, cố gắng giữ nó ở mức cao nhất thường liên quan đến việc tạo ra nhiều giao diện và phương thức đăng ký bổ sung. Nó là rất nhiều mã hóa cho ít được.

Giống như với bất kỳ khuôn khổ nào về sự tận tụy, sẽ dẫn bạn xuống một số ngõ hẻm lạ. Bạn cần phải sử dụng bản án để xem liệu có những kỹ thuật khác để sử dụng khi bạn nhận được một mùi mã xấu. Một lần nữa trong hộp thoại ý kiến ​​của tôi nên được ràng buộc chặt chẽ và được xác định bên cạnh lệnh sử dụng chúng. Bằng cách đó năm năm sau, tôi có thể quay trở lại phần mã đó và xem mọi thứ mà lệnh đó đang xử lý.

Một lần nữa trong một số ít trường hợp hộp thoại hữu ích cho nhiều lệnh, tôi xác định nó trong một mô-đun chung cho tất cả chúng. Tuy nhiên trong phần mềm của tôi có lẽ 1 trong số 20 hộp thoại là như thế này. Ngoại lệ chính là hộp thoại mở/lưu tệp. Nếu một hộp thoại được sử dụng bởi hàng chục lệnh thì tôi sẽ đi đường đầy đủ của việc định nghĩa một giao diện, tạo một biểu mẫu để thực hiện giao diện đó và đăng ký biểu mẫu đó.

Nếu nội địa hóa để sử dụng quốc tế là quan trọng đối với ứng dụng của bạn, bạn sẽ cần phải chắc chắn rằng bạn tài khoản cho điều đó với lược đồ này vì tất cả các biểu mẫu không có trong một mô-đun.

+0

Xin chào. Tôi nghĩ rằng có hộp thoại cụ thể trong ViewModel sẽ phá vỡ testability. –

0

Tôi cũng đã gặp sự cố này với MVVM. Suy nghĩ đầu tiên của tôi là cố gắng tìm cách không sử dụng hộp thoại. Sử dụng WPF nó dễ dàng hơn nhiều để đưa ra một cách slicker để làm việc hơn là với một hộp thoại.

Khi điều đó là không thể, tùy chọn tốt nhất có vẻ là để ViewModel gọi một lớp được chia sẻ để nhận thông tin từ người dùng. ViewModel hoàn toàn không biết rằng một hộp thoại đang được hiển thị. Vì vậy, như một ví dụ đơn giản, nếu bạn cần người dùng xác nhận việc xóa, ViewModel có thể gọi DialogHelper.ConfirmDeletion(), sẽ trả về một boolean cho dù người dùng đã nói có hay không. Việc hiển thị thực tế của hộp thoại sẽ được thực hiện trong lớp Helper.

Đối với các hộp thoại nâng cao hơn, trả về nhiều dữ liệu, phương thức trợ giúp sẽ trả về một đối tượng có tất cả thông tin từ hộp thoại trong đó.

Tôi đồng ý rằng nó không phù hợp nhất với phần còn lại của MVVM, nhưng tôi chưa tìm thấy bất kỳ ví dụ nào tốt hơn.

+0

gọi "DialogHelper.ConfirmDeletion()" thực sự gọi hộp thoại không tạo ra bất kỳ imho defference nào. Bạn vẫn đang trộn giao diện người dùng thuần túy trong mã. (sau khi tất cả, DialogHelper đã cho thấy đó là một helper cửa sổ ...) –

+0

Tôi đồng ý, nhưng tôi không thấy bất kỳ cách nào tốt hơn để làm điều này. Hộp thoại phải được hiển thị từ ViewModel để hoạt động. Tôi nghĩ rằng có ViewModel ít nhất là không hiển thị rõ ràng hộp thoại là một bước tốt, mặc dù. Các hộp thoại này có thể được tái sử dụng và được thay thế hoàn toàn bằng nỗ lực tối thiểu. – timothymcgrath

+0

Tôi nghĩ rằng có lẽ các sự kiện có thể là con đường để đi? Không chắc chắn về các chi tiết được nêu ra và làm thế nào nó phù hợp với MVVM thuần túy. –

0

Tôi phải nói, Dịch vụ là cách để đi tới đây.

Giao diện dịch vụ cung cấp cách trả lại dữ liệu. Sau đó, việc thực hiện thực tế của dịch vụ đó có thể hiển thị một hộp thoại hoặc bất cứ điều gì để có được thông tin cần thiết trong giao diện.

Cách đó để kiểm tra điều này, bạn có thể giả lập giao diện dịch vụ trong các thử nghiệm của bạn, và ViewModel không phải là người khôn ngoan hơn. Theo như ViewModel có liên quan, nó yêu cầu một dịch vụ cho một số thông tin và nó nhận được những gì nó cần.

+0

Xin chào. Ai sở hữu dịch vụ này? Xem hoặc Mô hình? Có vẻ như không đúng ở một trong những nơi đó. –

+0

Ý của bạn là ai sở hữu dịch vụ? Đó là một singleton. Ngoài ra nếu bạn nghĩ về những gì dịch vụ đang cung cấp thì đó là VM gọi nó vì đó là những gì cần xác nhận việc xóa, v.v. –

+0

Xin lỗi, ý tôi là 'không gian tên nào làm giao diện dịch vụ sống'. –

1

Trong bất động sản chẳng hạn Southridge của Jaime Rodriguez và Karl Shifflet, họ đang tạo ra các cửa sổ trong viewmodel, cụ thể hơn ở phần thi của một lệnh ràng buộc:

protected void OnShowDetails (object param) 
    { 
     // DetailsWindow window = new DetailsWindow(); 
     ListingDetailsWindow window = new ListingDetailsWindow(); 
     window.DataContext = new ListingDetailsViewModel (param as Listing, this.CurrentProfile) ; 
     ViewManager.Current.ShowWindow(window, true); 
    } 

Dưới đây là liên kết: http://blogs.msdn.com/jaimer/archive/2009/02/10/m-v-vm-training-day-sample-application-and-decks.aspx

Tôi đoán đó không phải là vấn đề lớn. Sau khi tất cả, ViewModel hoạt động như 'keo' giữa chế độ xem và lớp dữ liệu/lớp dữ liệu, vì vậy imho bình thường khi được ghép với Chế độ xem (UI) ...

+0

Cảm ơn bạn đã phản hồi. Điều này không có nghĩa là ViewModel có tham chiếu đến View cho ListingDetailsWindow (và cả ViewManager?). –

+1

Không, một ViewModel lý tưởng nên độc lập với công nghệ UI. Chắc chắn đó là keo, nhưng nó sẽ tránh bất kỳ sự phụ thuộc vào một cái nhìn cụ thể và, nếu có thể, bất kỳ sự phụ thuộc vào công cụ giao diện cụ thể/cơ khí. – Falcon

1

Onyx (http://www.codeplex.com/wpfonyx) sẽ cung cấp một cách công bằng giải pháp tốt đẹp cho việc này. Như một ví dụ, hãy nhìn vào dịch vụ ICommonDialogProvider, có thể được sử dụng từ một ViewModel như thế này:

ICommonFileDialogProvider provider = this.View.GetService<ICommonDialogProvider>(); 
IOpenFileDialog openDialog = provider.CreateOpenFileDialog(); 
// configure the IOpenFileDialog here... removed for brevity 
openDialog.ShowDialog(); 

này rất giống với việc sử dụng OpenFileDialog bê tông, nhưng là hoàn toàn có thể kiểm chứng. Số lượng tách bạn thực sự cần sẽ là chi tiết triển khai cho bạn. Ví dụ, trong trường hợp của bạn, bạn có thể muốn một dịch vụ hoàn toàn che giấu thực tế rằng bạn đang sử dụng một hộp thoại. Nội dung nào đó dọc theo dòng:

public interface IRemoveFiles 
{ 
    string[] GetFilesToRemove(); 
} 

IRemoveFiles removeFiles = this.View.GetService<IRemoveFiles>(); 
string[] files = removeFiles.GetFilesToRemove(); 

Sau đó, bạn phải đảm bảo Chế độ xem có triển khai cho dịch vụ IRemoveFiles, có một số tùy chọn có sẵn cho bạn.

Onyx chưa sẵn sàng để phát hành, nhưng mã hoạt động hoàn toàn và có thể sử dụng ít nhất là điểm tham chiếu. Tôi hy vọng sẽ phát hành ổn định giao diện V1 rất sớm, và sẽ phát hành ngay sau khi chúng tôi có tài liệu phong nha và mẫu.

+0

Xin chào. Các 'this.View.GetService()': Điều này does.View trở lại và nó sẽ cần một tham chiếu cụ thể cho bất kỳ loại trong không gian tên 'xem' của tôi? Với tôi, điều đó sẽ bắt đầu xuất hiện để phá vỡ MVVM - nhớ bạn, tôi có thể sai - Tôi rất mới với nó –

+0

Nó trả về một thể hiện View, một phần của khung công tác Onyx. View là một IServiceProvider và cũng cung cấp quyền truy cập vào ViewElement (phần tử trong đó View được liên kết), dưới dạng DependencyObject. Nếu bạn không bao giờ sử dụng ViewElement, bạn không vi phạm nguyên tắc MVVM. Kiểm tra các mẫu đơn giản. – wekempf

0

Những gì chúng ta đang làm là somethng như vậy, những gì được mô tả ở đây: http://www.codeproject.com/KB/WPF/DialogBehavior.aspx?msg=3439968#xx3439968xx

ViewModel có một tài sản đó được gọi là ConfirmDeletionViewModel. Ngay sau khi tôi đặt thuộc tính, Hành vi sẽ mở hộp thoại (phương thức hay không) và sử dụng ConfirmDeletionViewModel. Ngoài ra tôi đang chuyển một đại biểu được thực hiện khi người dùng muốn đóng hộp thoại. Về cơ bản, đây là một delegate đặt thuộc tính ConfirmDeletionViewModel thành null.

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