2013-07-18 36 views
11

Có cách nào để tự động cập nhật bộ lọc trên ICollectionView mà không cần phải gọi số Refresh() khi có thay đổi có liên quan không?Tự động làm mới Bộ lọc ICollectionView

tôi có như sau:

[Notify] 
public ICollectionView Workers { get; set; } 

Các [Thông báo] thuộc tính trong khách sạn này chỉ thực hiện INotifyPropertyChanged nhưng nó dường như không thể làm gì trong tình huống này.

Workers = new CollectionViewSource { Source = DataManager.Data.Workers }.View; 

Workers.Filter = w => 
    { 
     Worker worker = w as Worker; 
     if (w == null) 
      return false; 
     return worker.Employer == this; 
    }; 

Trong XAML:

<TextBlock x:Name="WorkersTextBlock" 
      DataContext="{Binding PlayerGuild}" 
      FontFamily="Pericles" 
      Text="{Binding Workers.Count, 
          StringFormat=Workers : {0}, 
          FallbackValue=Workers : 99}" /> 

Cập nhật: Dường như sử dụng ICollectionView sẽ là cần thiết đối với tôi, vì vậy tôi muốn xem xét lại vấn đề này. Tôi đang thêm tiền thưởng cho câu hỏi này, người nhận sẽ là người có thể cung cấp một số thông tin chi tiết về cách thực hiện 'hand-off' ICollectionView mà không cần phải được làm mới theo cách thủ công. Tại thời điểm này tôi mở cho bất kỳ ý tưởng.

+0

Vâng, xem xét thuộc tính đó không phải là BCL, nó không phải là đáng ngạc nhiên rằng nó không bao gồm các trường hợp góc này. Trong thực tế, không có bất cứ điều gì trong WPF bao gồm trường hợp này, vì vậy bạn sẽ phải làm điều đó cho mình. Thuộc tính bộ lọc không phải là DP và thậm chí là không có gì trong bộ lọc sẽ kích hoạt sự kiện cập nhật. Có vẻ như bạn sẽ phải kích hoạt nó theo cách thủ công. Có lẽ trong cơ thể của bộ lọc? Bạn có thể tự tham khảo thông qua việc đóng cửa. Nhìn vào lambda, bạn sẽ phải tắt cuộc gọi để làm mới đến Dispatcher, vì vậy nó sẽ chạy sau khi bộ lọc được áp dụng. Ergh và thêm khối bool "brb updating" – Will

+0

(không có nhiều ký tự) trông giống như không có cách nào xung quanh nó, ngoại trừ có thể mở rộng CVS và cập nhật trong bộ lọc, với kiểm tra để đảm bảo bạn không liên tục kích hoạt một bản cập nhật. Làm cho tinh thần tại sao đó không phải là BCL, phải không? Bộ lọc kích hoạt bản cập nhật, kích hoạt bộ lọc, và bật và bật ... – Will

+0

Cảm ơn bạn đã giải thích. Có vẻ như tôi sẽ làm điều này bằng tay. –

Trả lời

13

AFAIK không có hỗ trợ sẵn có trong ICollectionView để làm mới bộ sưu tập về bất kỳ thay đổi thuộc tính nào trong bộ sưu tập nguồn cơ bản.

Nhưng bạn có thể phân lớp ListCollectionView để cung cấp cho bản triển khai của riêng bạn refresh collection on any property changed. Sample -

public class MyCollectionView : ListCollectionView 
{ 
    public MyCollectionView(IList sourceCollection) : base(sourceCollection) 
    { 
     foreach (var item in sourceCollection) 
     { 
      if (item is INotifyPropertyChanged) 
      { 
       ((INotifyPropertyChanged)item).PropertyChanged += 
                (s, e) => Refresh(); 
      } 
     } 
    } 
} 

Bạn có thể sử dụng trong dự án của bạn như thế này -

Workers = new MyCollectionView(DataManager.Data.Workers); 

Điều này có thể được tái sử dụng qua dự án của bạn mà không cần phải lo lắng để làm mới bộ sưu tập trên mỗi PropertyChanged.MyCollectionView sẽ làm điều đó automatically cho bạn.

HOẶC

Nếu bạn đang sử dụng .Net4.5 bạn có thể đi với ICollectionViewLiveShaping thực hiện như mô tả here.

Tôi đã đăng phần triển khai cho sự cố của bạn tại đây - Implementing ICollectionViewLiveShaping.

đang làm việc từ bài đó -

public ICollectionViewLiveShaping WorkersEmployed { get; set; } 

ICollectionView workersCV = new CollectionViewSource 
         { Source = GameContainer.Game.Workers }.View; 

ApplyFilter(workersCV); 

WorkersEmployed = workersCV as ICollectionViewLiveShaping; 
if (WorkersEmployed.CanChangeLiveFiltering) 
{ 
    WorkersEmployed.LiveFilteringProperties.Add("EmployerID"); 
    WorkersEmployed.IsLiveFiltering = true; 
} 
+0

Cách tiếp cận phân lớp hoạt động hoàn hảo! Cảm ơn bạn! –

+0

Vâng, sắp xếp. Khi một mục mới được thêm vào bộ sưu tập, nó không được xử lý đúng cách vì logic nằm trong hàm tạo. Tôi sẽ chơi xung quanh với điều này một chút và xem những gì tôi có thể làm. –

+1

Thực ra, việc triển khai 'ICollectionViewLiveShaping' này cũng hoạt động. Ban đầu tôi không biết mình đã làm gì sai khi tôi thử câu trả lời của bạn. Cảm ơn một lần nữa! –

8

Đối Net 4.5: Có một giao diện mới mà có thể giúp để đạt được tính năng này, được gọi là: ICollectionViewLiveShaping.

Từ MSDN link:

Khi sống phân loại, nhóm, hoặc lọc được kích hoạt, một CollectionView sẽ sắp xếp lại vị trí của dữ liệu trong CollectionView khi dữ liệu được sửa đổi. Ví dụ: giả sử ứng dụng sử dụng DataGrid để liệt kê các cổ phiếu trên thị trường chứng khoán và các cổ phiếu được sắp xếp theo giá trị cổ phiếu . Nếu sắp xếp trực tiếp được bật trên CollectionView của cổ phiếu, vị trí của một cổ phiếu trong DataGrid sẽ di chuyển khi giá trị của cổ phiếu trở nên lớn hơn hoặc nhỏ hơn giá trị của một cổ phiếu khác.

More Info trên giao diện trên: http://www.jonathanantoine.com/2011/10/05/wpf-4-5-%E2%80%93-part-10-live-shaping/


Đối Net 4 và thấp: Ngoài ra còn có một bài đăng trên SO QA mà có thể giúp bạn: CollectionViewSource Filter not refreshed when Source is changed

+0

Nếu bạn có thể giúp tôi làm việc này, tiền thưởng chắc chắn sẽ đến với bạn. Tôi đã đăng câu hỏi về việc triển khai 'ICollectionViewLiveShaping' tại đây: http://stackoverflow.com/questions/17865202/implementing-icollectionviewliveshaping –

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