2011-06-30 31 views
5

Tôi đang có một thời gian tìm ra cách xử lý một Chủ đề từ một lớp bên ngoài ViewModel của tôi.Làm thế nào để xử lý chủ đề C# WPF trong mô hình xem MVVM

Chủ đề bắt nguồn từ lớp Track. Đây là ResponseEventHandler mã trong Track:

public delegate void ResponseEventHandler(AbstractResponse response); 
public event ResponseEventHandler OnResponseEvent; 

Khi một phương pháp "lệnh" được xử lý từ bên trong đối tượng Track của tôi, đoạn code sau chạy OnResponseEvent, mà gửi một thông điệp trong một chủ đề trở lại ViewModel của tôi:

if (OnResponseEvent != null) 
{ 
    OnResponseEvent(GetResponseFromCurrentBuffer()); 
} 

GetResponseFromCurrentBuffer() chỉ trả về loại thông báo là loại được xác định trước trong số Track.

constructor MainWindowViewModel tôi tạo ra một event handler cho OnResponseEvent từ Track:

public MainWindowViewModel() 
{ 
    Track _Track = new Track(); 

    _Track.OnResponseEvent += 
     new Track.ResponseEventHandler(UpdateTrackResponseWindow); 
} 

Vì vậy, ý tưởng là mỗi khi tôi có một tin nhắn mới đến từ các OnResponseEvent Chủ đề, tôi chạy phương pháp UpdateTrackResponseWindow(). Phương pháp này sẽ nối thêm một chuỗi thông điệp mới cho một tài sản được gọi TrackResponseMessage danh sách ObservableCollection<string>:

private void UpdateTrackResponseWindow(AbstractResponse message) 
{ 
    TrackResponseMessage.Add(FormatMessageResponseToString(message)); 
} 

Phương pháp FormatMessageResponseToString() chỉ đơn thuần so sánh nhắn với tất cả các loại tin nhắn được xác định trước trong Track, và làm một số định dạng chuỗi tiện lợi.

Vấn đề chính là: Giao diện người dùng biến mất khi TrackResponseMessage.Add() chạy. Thực thi vẫn chạy ở chế độ nền, và cách duy nhất để kết thúc nhiệm vụ là để tắt Visual Studio 2010.

TrackResponseMessage là một tài sản công trong ViewModel của tôi:

public ObservableCollection<String> TrackResponseMessage 
{ 
    get { return _trackResponseMessage; } 
    set 
    { 
     _trackResponseMessage = value; 
     RaisePropertyChanged("TrackResponseMessage"); 
    } 
} 

Có một nhu cầu cho tôi để soái các Thread đến từ các đối tượng Track để ViewModel của tôi? Bất kỳ mã ví dụ nào cũng sẽ được đánh giá cao!

Trả lời

9

Tôi có cần phải sắp xếp lại chuỗi bắt đầu từ đối tượng Track.cs vào chế độ xem của tôi không? Bất kỳ mã ví dụ nào cũng sẽ được đánh giá cao!

Có. Thật không may, trong khi INotifyPropertyChanged sẽ xử lý các sự kiện từ các chủ đề khác, INotifyCollectionChanged không (ví dụ: ObservableCollection<T>). Như vậy, bạn cần sắp xếp lại máy ảo.

Nếu máy ảo đang được tạo từ Chế độ xem (MVVM chế độ xem đầu tiên) hoặc được biết là được tạo trên chuỗi giao diện người dùng, có một tùy chọn tốt khi sử dụng.NET 4 nhiệm vụ:

TaskScheduler uiScheduler; 
public MainWindowViewModel() 
{ 
    uiScheduler = TaskScheduler.FromCurrentSynchronizationContext(); 
    Track _Track = new Track(); 
    _Track.OnResponseEvent += new Track.ResponseEventHandler(UpdateTrackResponseWindow); 
} 

Sau đó, sau đó, xử lý sự kiện của bạn có thể làm:

private void UpdateTrackResponseWindow(AbstractResponse message) 
{ 
    Task.Factory.StartNew(
     () => TrackResponseMessage.Add(FormatMessageResponseToString(message)), 
     CancellationToken.None, TaskCreationOptions.None, 
     uiScheduler); 
} 

này có lợi thế tốt đẹp của không kéo WPF hoặc Silverlight nguồn lực và các loại cụ thể vào lớp ViewModel của bạn (ví dụ: Dispatcher), trong khi vẫn cung cấp tất cả các lợi ích. Nó cũng hoạt động, không thay đổi, trong các thói quen khác có ái lực luồng (ví dụ: công việc phục vụ WCF).

+0

Yeeehaw !! Nó hoạt động rất tốt! Reed, tôi nợ bạn một chiếc bánh rán! Bạn đã tiết kiệm cho tôi số giờ đọc tài liệu luồng .net. TaskScheduler giúp bạn dễ dàng đọc các luồng đang phát sinh từ các đối tượng lớp khác trong viewmodel của tôi. – EnLaCucha

+0

@EnLaCucha: FYI - Điều này chỉ hoạt động cho các chủ đề có cài đặt SynchronizationContext. Đó là sự thật cho chủ đề chính của WPF, chủ đề chính của WinForms, và các cuộc gọi dịch vụ WCF, mặc dù. –

+0

Với .net 4.5, bây giờ bạn có thể chỉnh sửa bộ sưu tập từ một chuỗi khác bằng BindingOperations.EnableCollectionSynchronization https://msdn.microsoft.com/en-us/library/hh140164(v=vs.110).aspx – Kelly

0

Nếu RaisePropertychanged được thực hiện trên một chuỗi khác với chuỗi giao diện người dùng VÀ trình xử lý sự kiện cho sự kiện chạm vào giao diện người dùng bạn cần chuyển sang chuỗi giao diện người dùng.

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