2017-12-06 20 views
1

を変更したときにフィルターを再評価しません。LiveFilteringは、リスト内のアイテムのプロパティは、私は、プロパティ名のためにINotifyPropertyChangedのを実装するクラスの人を、持っている

var coll = new ObservableCollection<Person>(); 
ListCollectionView view = new ListCollectionView(coll) 
{ 
    Filter = p => ((Person)p).Name[0]=='A', 
    IsLiveFiltering = true, 
    LiveFilteringProperties = { nameof(Person.Name) } 
}; 

アイテムがコレクションに追加されている場合、それらが正しくフィルタされています。名前が「A」で始まる人だけを一致させるためのフィルタのObservableCollectionを、表示します
問題: Personの名前が変更されたとき、最初にIsLiveFilteringとLiveFilteringPropertiesがあると思ったフィルタが再評価されません。 "Anna"から "Elsa"に名前を変更した場合、ビューが更新され、アイテムが含まれなくなるはずです。同様に、「Eric」を「Arnold」に変更すると、変更された項目がビューのコンテナになるようにビューが更新されます。

var p1 = new Person { Name = "Anna" }; 
var p2 = new Person { Name = "Eric" }; 

coll.Add(p1); // view is updated automatically and contains Anna now 
coll.Add(p2); // view is updated, but Eric is filtered out 

view.Dump(); // shows only "Anna" (LINQPad - Dump) 

p1.Name = "Elsa"; // change Anna to Elsa -> the instance p1 should be removed from view (not from collection) 
p2.Name = "Arnold"; // change Eric to Arnold -> the instance p2 should now be in the view 

//view.Refresh(); // uncommenting this line leads to the behaviour I actually expected from LiveFiltering to be handled automatically. 

view.Dump(); // shows "Elsa", but we are filtering for A* 

この現象が発生するのを忘れましたか? Personの各インスタンスのPropertyChangedに手動でアタッチしたいとは思っていません。私はこれがLiveFilteringが私にとって何をしているのかと期待しています。

編集: 大きなモデルで私のアプリケーションで問題が発生し、LinqPadで問題を再現するために関連する部分を抽出しました。ここにLinqPadの完全なスクリプトがあります。また、使用して句を必要とします:

using System.Collections.ObjectModel; 
using System.Windows.Data; 
using System.ComponentModel; 

ここだスクリプト

void Main() 
{ 
    var coll = new ObservableCollection<Person>(); 
    ListCollectionView view = new ListCollectionView(coll) 
    { 
     IsLiveFiltering = true, 
     LiveFilteringProperties = { nameof(Person.Name) }, 
     Filter = p => ((Person)p).Name[0] == 'A' 
    }; 

    var p1 = new Person { Name = "Anna" }; 
    var p2 = new Person { Name = "Eric" }; 

    coll.Add(p1); 
    coll.Add(p2); 

    view.Dump(); 

    p1.Name = "Elsa"; 
    p2.Name = "Arnold"; 

    //view.Refresh(); 

    view.Dump(); 
    Debug.Assert(view.Cast<Person>().Single().Name == "Arnold", "Wrong item in view, expected Arnold"); 
} 

public class Person : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    private void OnPropertyChanged(string property) 
    { 
     Console.WriteLine("PropertyChanged: " + Name + ": " + property); 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); 
    } 

    private string _name; 
    public string Name 
    { 
     get => _name; 
     set 
     { 
      if (_name == value) 
       return; 
      _name = value; 
      OnPropertyChanged("Name"); 
     } 
    } 
} 

答えて

1

はどこビューとサンプルデータですか...?

次のコードは、期待どおり動作します。

XAML:

<ListBox x:Name="lb" DisplayMemberPath="Name" /> 
<Button Content="Filter" Click="Button_Click" /> 

サンプルコード:

public partial class MainWindow : Window 
{ 
    Person _p = new Person() { Name = "Anna" }; 

    public MainWindow() 
    { 
     InitializeComponent(); 

     var coll = new ObservableCollection<Person>() { _p }; 
     ListCollectionView view = new ListCollectionView(coll) 
     { 
      Filter = p => ((Person)p).Name[0] == 'A', 
      IsLiveFiltering = true, 
      LiveFilteringProperties = { nameof(Person.Name) } 
     }; 

     lb.ItemsSource = view; 
    } 

    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     _p.Name = "Elsa"; 
    } 
} 

あなたは別の質問を投稿する前に、あなたはおそらくthisをお読みください。

+0

問題に再現するために使用した完全なLinqPadスクリプトを追加しました。うまくいけば、間違いが見えるようになります。 – Michael

+0

ライブフィルタリングは、サンプルコードが明らかに示すように、実際にイベントのサブスクライバが存在する場合、WPFアプリケーションのコンテキストで確実に機能します。 Linqpadで動作しない場合、LinqPadに問題があり、ListCollectionViewには問題があります。 – mm8

+0

もちろん、それは絶対に真です。私が "バグ"を分離してLinqPadで再現しようとしたとき、私はLinqPadがもちろんコレクションビューのイベントに登録していないことに気付かなかった。投稿したコードはもちろん動作し、LiveFiltering機能から期待した動作です。 私のアプリで最初に経験したバグは、別の場所に導入されました。すべてが期待どおりに機能するので(私がうんざりしない限り)、私はこれに答えてマークします。 – Michael

関連する問題