2009-03-19 21 views
12

Tôi có một ListView WPF ràng buộc với một CollectionViewSource. Nguồn của liên kết đó được gắn với thuộc tính, có thể thay đổi nếu người dùng chọn một tùy chọn.CollectionViewSource Bộ lọc không được làm mới khi Nguồn được thay đổi

Khi nguồn chế độ xem danh sách được cập nhật do sự kiện đã thay đổi thuộc tính, mọi thứ cập nhật chính xác, nhưng chế độ xem không được làm mới để xem xét bất kỳ thay đổi nào trong bộ lọc CollectionViewSource.

Nếu tôi đính kèm một trình xử lý vào sự kiện đã thay đổi mà thuộc tính nguồn được ràng buộc với tôi có thể làm mới chế độ xem, nhưng đây vẫn là chế độ xem cũ, vì ràng buộc chưa cập nhật danh sách.

Có cách nào hiệu quả để làm mới chế độ xem và đánh giá lại bộ lọc khi nguồn thay đổi không?

Cheers

+1

Trong trường hợp có ai tìm thấy này, nó là một chút ra khỏi ngày bây giờ. Trong WPF 4.5, các tính năng mới được thêm vào để cho phép sắp xếp, lọc và nhóm "Live". Xem http://www.jonathanantoine.com/2011/10/05/wpf-4-5-%E2%80%93-part-10-live-shaping/ –

Trả lời

2

Bạn đang làm thay đổi bộ sưu tập ví dụ thực tế giao cho CollectionViewSource.Source, hoặc là bạn chỉ cần bắn PropertyChanged trên tài sản mà nó là ràng buộc để?

Nếu thuộc tính Source được đặt, bộ lọc sẽ được thu hồi cho mọi mục trong bộ sưu tập nguồn mới, vì vậy tôi đang nghĩ điều gì đó khác đang xảy ra. Bạn đã thử đặt Source theo cách thủ công thay vì sử dụng ràng buộc và xem liệu bạn có nhận được hành vi của mình không?

Edit:

Bạn đang sử dụng CollectionViewSource.View.Filter tài sản, hoặc sự kiện CollectionViewSource.Filter? CollectionView sẽ bị thổi bay khi bạn đặt Source mới, vì vậy nếu bạn có một Filter đặt trên CollectionView nó sẽ không còn ở đó nữa.

+0

Có, tôi đang thay đổi bộ sưu tập và các mục trong chế độ xem danh sách được cập nhật phản ánh bộ sưu tập mới. Tuy nhiên, bộ lọc không được đánh giá lại. Làm điều đó bằng tay không giúp: ((CollectionViewSource) this.Resources ["logEntryViewSource"]). Source = _application.CurrentLog.Entries.ObservableCollection – Steve

12

Một hơi muộn có lẽ, nhưng điều này có thể giúp người dùng khác vì vậy tôi sẽ đăng anyway ...

Cập nhật CollectionView.Filter dựa trên một sự kiện PropertyChanged không được hỗ trợ bởi framework. Có một số giải pháp xung quanh vấn đề này.

1) Triển khai giao diện IEditableObject trên các đối tượng bên trong bộ sưu tập của bạn và gọi BeginEdit và EndEdit khi thay đổi thuộc tính mà bộ lọc dựa vào. Bạn có thể đọc thêm về điều này trên blog tuyệt vời của Dr.WPF tại đây: Editable Collections by Dr.WPF

2) Tạo lớp sau và sử dụng chức năng RefreshFilter trên đối tượng đã thay đổi.

public class FilteredObservableCollection<T> : ObservableCollection<T> 
{ 
    public void RefreshFilter(T changedobject) 
    { 
     OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, changedobject, changedobject)); 
    }   
} 

Ví dụ:

public class TestClass : INotifyPropertyChanged 
{ 
    private string _TestProp; 
    public string TestProp 
    { 
     get{ return _TestProp; } 
     set 
     { 
      _TestProp = value; 
      RaisePropertyChanged("TestProp"); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected void RaisePropertyChanged(string propertyName) 
    { 
     var handler = this.PropertyChanged; 
     if (handler != null) 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 


FilteredObservableCollection<TestClass> TestCollection = new FilteredObservableCollection<TestClass>(); 

void TestClass_PropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
    switch (e.PropertyName) 
    { 
     case "TestProp": 
      TestCollection.RefreshFilter(sender as TestClass); 
      break; 
    } 
} 

Theo dõi sự kiện PropertyChanged của đối tượng TestClass khi bạn tạo ra nó, nhưng đừng quên để mở móc các eventhandler khi đối tượng bị loại bỏ, nếu không điều này có thể dẫn đến bộ nhớ bị rò rỉ

HOẶC

Chích TestCollection vào TestClass và sử dụng chức năng RefreshFilter bên trong setter TestProp. Nhưng dù sao, phép thuật ở đây được làm việc bởi NotifyCollectionChangedAction.Replace để cập nhật hoàn toàn mục đó.

+0

Tôi hiện đang bị mắc kẹt với .NET 4.0 và giải pháp IEditableObject hoạt động như một sự quyến rũ. – Golvellius

+0

Tôi không thể nhận được IEditableObject hoạt động. Nhưng FilteredObservableCollection hoạt động rất tốt. Cảm ơn vì giải pháp –

2

Tôi đã tìm thấy giải pháp cụ thể để mở rộng lớp ObservableCollection thành lớp giám sát các thay đổi trong thuộc tính của đối tượng chứa here.

Dưới đây là mã đó với một vài sửa đổi bởi tôi:

namespace Solution 
{ 
public class ObservableCollectionEx<T> : ObservableCollection<T> where T : INotifyPropertyChanged 
    { 
     protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) 
     { 
      if (e != null) // There's been an addition or removal of items from the Collection 
      { 
       Unsubscribe(e.OldItems); 
       Subscribe(e.NewItems); 
       base.OnCollectionChanged(e); 
      } 
      else 
      { 
       // Just a property has changed, so reset the Collection. 
       base.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); 

      } 

     } 

     protected override void ClearItems() 
     { 
      foreach (T element in this) 
       element.PropertyChanged -= ContainedElementChanged; 

      base.ClearItems(); 
     } 

     private void Subscribe(IList iList) 
     { 
      if (iList != null) 
      { 
       foreach (T element in iList) 
        element.PropertyChanged += ContainedElementChanged; 
      } 
     } 

     private void Unsubscribe(IList iList) 
     { 
      if (iList != null) 
      { 
       foreach (T element in iList) 
        element.PropertyChanged -= ContainedElementChanged; 
      } 
     } 

     private void ContainedElementChanged(object sender, PropertyChangedEventArgs e) 
     { 
      OnPropertyChanged(e); 
      // Tell the Collection that the property has changed 
      this.OnCollectionChanged(null); 

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