2010-11-29 32 views
8

Khi sử dụng dữ liệu WPF, tôi rõ ràng không thể làm điều gì đó dọc theo các dòng MyCollection = new CollectionType<Whatever>(WhateverQuery()); vì các ràng buộc có tham chiếu đến bộ sưu tập cũ. Workaround của tôi cho đến nay đã được MyCollection.Clear(); theo sau là một foreach làm MyCollection.Add(item); - đó là khá xấu cho cả hiệu suất và thẩm mỹ.WPF: Thay thế nội dung thu thập dữ liệu mà không cần Xóa/Thêm

ICollectionView, mặc dù khá gọn gàng, không giải quyết được sự cố vì đó là thuộc tính SourceCollection chỉ đọc; thật đáng tiếc, vì đó sẽ là một giải pháp tốt đẹp và dễ dàng.

Những người khác xử lý vấn đề này như thế nào? Nó nên được đề cập rằng tôi đang làm MVVM và do đó không thể lục lọi thông qua các ràng buộc điều khiển cá nhân. Tôi cho rằng tôi có thể làm cho một wrapper quanh ObservableCollection thể thao một phương pháp ReplaceSourceCollection(), nhưng trước khi đi tuyến đường đó tôi muốn biết nếu có một số thực hành tốt nhất khác.

EDIT:

Đối với WinForms, tôi sẽ ràng buộc điều khiển chống lại một BindingSource, cho phép tôi chỉ đơn giản là cập nhật nó DataSource tài sản và gọi phương thức ResetBindings() - mau, nằm bên dưới bộ sưu tập đã thay đổi một cách hiệu quả. Tôi đã có thể dự kiến ​​WPF databinding để hỗ trợ một kịch bản tương tự ra khỏi hộp?

Mã ví dụ (pseudo-ish): Điều khiển WPF (ListBox, DataGrid, bất kỳ thứ gì bạn ưa thích) được gắn với thuộc tính Users. Tôi nhận ra rằng bộ sưu tập nên chỉ đọc để tránh những vấn đề được chứng minh bởi ReloadUsersBad(), nhưng sau đó các mã xấu ví dụ này rõ ràng sẽ không biên dịch :)

public class UserEditorViewModel 
{ 
    public ObservableCollection<UserViewModel> Users { get; set; } 

    public IEnumerable<UserViewModel> LoadUsersFromWhateverSource() { /* ... */ } 

    public void ReloadUsersBad() 
    { 
     // bad: the collection is updated, but the WPF control is bound to the old reference. 
     Users = new ObservableCollection<User>(LoadUsersFromWhateverSource()); 
    } 

    public void ReloadUsersWorksButIsInefficient() 
    { 
     // works: collection object is kept, and items are replaced; inefficient, though. 
     Users.Clear(); 
     foreach(var user in LoadUsersFromWhateverSource()) 
      Users.Add(user); 
    } 

    // ...whatever other stuff. 
} 
+0

bạn có thể vui lòng đăng một số mã không? – TalentTuner

+0

+1 câu hỏi hay. Tôi đã không làm bất cứ điều gì trong WPF một thời gian, nhưng một khuôn khổ khác trong một ngôn ngữ khác nhau có khái niệm tương tự và giải quyết vấn đề này bằng cách tạm dừng vòng lặp chạy, thay đổi một số lượng lớn các thuộc tính, và sau đó bỏ tạm dừng vòng lặp chạy. Tôi đang tìm một cái gì đó tương tự. –

Trả lời

4

Nếu đối tượng MyCollection là công cụ INotifyPropertyChanged, bạn chỉ cần thay thế bộ sưu tập.

Một ví dụ:

public class MyClass : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    private ObservableCollection<Whatever> _myCollection; 

    private void NotifyChanged(string property) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(property)); 
    } 

    public ObservableCollection<Whatever> MyCollection 
    { 
     get 
     { 
      return _myCollection; 
     } 
     set 
     { 
      if (!ReferenceEquals(_myCollection, value)) 
      { 
       _myCollection = value; 
       NotifyChanged("MyCollection"); 
      } 
     } 
    } 
} 

Với điều này, khi bạn gán một bộ sưu tập, WPF phát hiện này và tất cả mọi thứ được cập nhật.

Đây là cách tôi giải quyết vấn đề này.

+0

Tất nhiên ... Tôi khá chắc chắn rằng tôi thậm chí đã phải làm điều đó trước đây. –

+0

D'oh!Nó phải là một cái gì đó đơn giản và rõ ràng, phải không? : P – snemarch

+0

Không sao, tôi rất vui được giúp đỡ. –

1

Các liên kết dưới đây giải thích làm thế nào để thực hiện một phương pháp AddRange.

http://blogs.msdn.com/b/nathannesbit/archive/2009/04/20/addrange-and-observablecollection.aspx

Dường như bạn đang mắc kẹt với thực hiện một sub-class để xử lý trường hợp này một cách chính xác.

Rõ ràng, các điều khiển nhất định không hỗ trợ thông báo thay đổi bộ sưu tập theo lô. Ít nhất là họ đã không viết bài báo đó. Mặc dù bây giờ bạn sẽ có thêm một chút thông tin nếu bạn muốn điều tra thêm.

+0

Bài viết về việc xử lý các cập nhật theo lô (thay vì hoàn toàn thay thế) - khó chịu khi 'ListCollectionView' chỉ hỗ trợ cập nhật một mục: | – snemarch

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