2010-03-12 14 views
5

Ứng dụng WPF của tôi được cấu trúc bằng mẫu MVVM. ViewModels sẽ giao tiếp không đồng bộ với một máy chủ và khi dữ liệu được yêu cầu được trả về, một cuộc gọi lại trong ViewModel được kích hoạt và nó sẽ làm điều gì đó với dữ liệu này. Điều này sẽ chạy trên một chuỗi không phải là Giao diện người dùng. Đôi khi những callback này liên quan đến công việc cần được thực hiện trên luồng UI, vì vậy tôi cần Dispatcher. Đây có thể là những thứ như:Việc coi các đối tượng ViewModel có giữ được Dispatcher không?

  • Thêm dữ liệu vào một ObservableCollection
  • lệnh kích hoạt Prism rằng sẽ thiết lập một cái gì đó sẽ được hiển thị trong giao diện
  • Tạo các đối tượng WPF của một số loại.

Tôi cố gắng tránh điều sau, nhưng hai điểm đầu tiên ở đây tôi thấy là những điều hợp lý để ViewModels thực hiện. Vì thế; sao ViewModels có giữ Dispatcher để có thể gọi các lệnh cho thread UI? Hay đây có phải là hành vi xấu? Và tại sao?

+0

Tôi đã phải làm tương tự trong bộ điều khiển - bộ điều khiển đăng ký sự kiện Load của khung nhìn nó tạo ra, và tại điểm đó lấy một tham chiếu đến bộ điều phối của khung nhìn. Điều này đặc biệt hữu ích cho việc thực hiện các đại biểu đã được thông qua. – slugster

+0

Thx cho đầu!Tôi đang sử dụng một container IoC và container IoC được tạo trong App.xaml.cs. Tôi giả sử điều này được chạy trong thread UI, vì vậy kế hoạch là lấy bộ điều phối hiện tại tại điểm mà thùng chứa IoC được tạo và thêm nó vào thùng chứa. Vẫn còn để xem nếu điều này là thành công. – stiank81

+0

Hoạt động hoàn hảo. Hoặc bạn có thể chỉ cần sử dụng Dispatcher.CurrentDispatcher tại bất kỳ parh bạn biết đang được chạy bởi các chủ đề giao diện người dùng. Ví dụ: các nhà xây dựng ViewModel - nếu chúng được xây dựng trong chuỗi giao diện người dùng. – stiank81

Trả lời

3

Vì một ObservableCollection phải được cập nhật trên chuỗi nó thuộc về (giả sử ứng dụng GUI) và ObservableCollections phải là một phần của ViewModel, thì có trường hợp rõ ràng cho ViewModel có Dispatcher.

Tôi không thể thấy nó là một phần của Mô hình.

+0

Nó chắc chắn không phải là một phần của mô hình. Cách giải quyết bạn có thể làm là tạo một ObservableCollection mới và điền vào kết quả với điều này, nhưng điều đó thực sự giống như một hack cho tôi .. – stiank81

+0

Tôi có một biến thể nhỏ của MVVM: Mô hình của tôi là mã không được quản lý chạy trên các chuỗi công nhân. Mô hình gọi lại vào mã .Net của tôi, sau đó gửi đi đến luồng GUI. Chức năng được gửi chạy trong luồng GUI sau đó cập nhật ViewModel. Bằng cách này, máy ảo của tôi không cần biết về việc gửi đi. – Surfbutler

1

Tôi đồng ý với kyoryu và tôi muốn lưu ý rằng nó chỉ tạo phụ thuộc vào trụ sở ServiceModel (mà bạn đã có) chứ không phải trên chính Chế độ xem, vì vậy có rất ít đối tượng chống lại việc xây dựng này.

Tôi đã thử một vài điều với WPF, một máy ảo và chủ đề đơn giản ngày hôm qua và đi đến kết luận rằng tôi hoàn toàn cần phải chuyển Người điều phối đến máy ảo.

Xem thêm Using WPF UI thread should always ensure STA apartment mode, right?

+0

Thx cho câu trả lời của bạn! Tôi bắt đầu sử dụng Dispatcher ngay bây giờ, và nó thực sự đơn giản hóa mọi thứ. Trước khi tôi làm điều này tôi thấy mình đang làm một số giải pháp rất sáng tạo (hacky). Sử dụng Dispathcer, tôi nghĩ rằng mã này sẽ tốt hơn rất nhiều. Nhưng tôi đoán bạn nên nhận thức được những gì bạn làm - không làm * bất cứ điều gì * chỉ vì bạn có thể .. – stiank81

+0

Vượt qua Dispatcher đến VM? Đó có lẽ không phải là điều tôi muốn làm. Quan điểm của tôi là VM có thể cần một Dispatcher vì nó có thể sở hữu những thứ cần được Dipsatached. Thông thường, tôi thích thực hiện việc gửi đi của tôi vào giây phút cuối cùng có thể. Nếu đó là VM, tốt, nếu nó trong View, tốt. Nếu View của tôi là hoàn toàn xaml, tôi có thể bị cám dỗ để có VM chịu trách nhiệm cho Dispatcher, chỉ để giữ View pure xaml. Nhưng đó có lẽ là quá thông minh trên phần m. – kyoryu

+0

Tất nhiên, điều này có thể là vì trong công việc ban ngày của tôi, tôi đang làm việc trên các bit cơ sở hạ tầng và chúng tôi đang cố gắng sở hữu bối cảnh luồng. Và tôi nhanh chóng đi đến kết luận rằng có ý nghĩa hơn khi làm điều đó cho các bit thực sự quan tâm nhất có thể, thay vì tập trung nó ... – kyoryu

2

Lý tưởng nhất, một ViewModel nên được hoàn toàn độc lập với công nghệ giao diện người dùng sử dụng. Chúng tôi về mặt lý thuyết có thể sử dụng lại nó cho Biểu mẫu Windows (nếu chúng tôi pimp lên Biểu mẫu Windows kiểm soát một chút để hỗ trợ ràng buộc tốt hơn), cho Trang web (Tôi hình dung một số cơ chế ưa thích ở đây sẽ biên dịch số ViewModel cũng vào Javascript) và cho bất kỳ công nghệ nào trong tương lai. Không phải tất cả các công nghệ này sẽ sử dụng mô hình Dispatcher.

Điều đó nói rằng, tôi coi đó là một thỏa hiệp thực dụng để bao gồm Dispatcher trong ViewModel ngày nay. Trong lớp cơ sở ViewModel của tôi, tôi kiểm tra sự hiện Dispatcher:

protected override void OnPropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
     if (Deployment.Current.Dispatcher == null || Deployment.Current.Dispatcher.CheckAccess()) 
     { 
      base.OnPropertyChanged(sender, e); 
     } 
     else 
     { 
      Deployment.Current.Dispatcher.BeginInvoke(() => base.OnPropertyChanged(sender, e)); 
     } 
    } 

tôi vẫn có sự phụ thuộc vào System.Windows tất nhiên, nhưng oh well. : ->

+0

Nghe có vẻ hay khi có thể sử dụng lại Chế độ xem của bạn, nhưng tôi thực sự không đồng ý rằng đây là mục tiêu. Chỉ cần xem xét một điều đơn giản như ràng buộc lệnh. Bạn thực sự cần các ràng buộc lệnh khi thực hiện MVVM, nhưng Winforms có ICommand không? Thực ra tôi không chắc chắn, nhưng trước đó tôi muốn làm cho ViewModels của tôi được xây dựng trên Mono, và ít nhất Mono không có ICommand .. – stiank81

+0

Vẫn - phản hồi có giá trị! +1 – stiank81

+1

@heartmaster, nếu nó (thực sự) là mục tiêu để sử dụng lại máy ảo của bạn, bạn nên ẩn điều phối đi sau một số giao diện (cũng có thể được thực hiện lại bởi WinForms InvokeRequired, v.v.). –

0

Thay vào đó, bạn nên cân nhắc sử dụng AsyncOperation.

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