3

C#:

public partial class MainWindow : Window
{
    private readonly ViewModel vm;

    public MainWindow()
    {
        InitializeComponent();
        vm = new ViewModel();

        DataContext = vm;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        vm.Models.RemoveAt(0);
    }
}

public class ViewModel
{
    public ObservableCollection<Model> Models { get; set; }
    public ListCollectionView View { get; set; }

    public ViewModel()
    {
        Models = new ObservableCollection<Model>()
        {
            new Model() { Name = "Gordon Freeman" },
            new Model() { Name = "Isaac Kleiner" },
            new Model() { Name = "Eli Vance" },
            new Model() { Name = "Alyx Vance" },
        };

        Models.CollectionChanged += (s, e) => View.Refresh();
        View = new ListCollectionView(Models);
    }
}

public class Model
{
    public string Name { get; set; }

    public override string ToString()
    {
        return Name;
    }
}

XAML:

<StackPanel>
    <ListBox ItemsSource="{Binding Path=View}" />
    <Button Click="Button_Click">Click</Button>
</StackPanel>

ObservableCollection には 4 つの要素が含まれており、期待どおり、ListBox には 4 つすべてが表示されています。ボタンをクリックすると、ObservableCollection の最初の要素が削除されます。ただし、ListBox は現在、2 番目と 3 番目のみを表示しています。1番目と4番目が削除されたようです。

行がModels.CollectionChanged += (s, e) => View.Refresh();に移動された(または完全にコメントアウトされた) 場合、期待どおりに機能します。 View = new ListCollectionView(Models);

なんで?

PS これは大きなパズルの単純なピースです。View.Refresh();この小さな例では、ListBox 自体を更新するために CollectionChangedを呼び出す必要がないことに気付きました。

4

4 に答える 4

1

私の推測では、更新がビューによる自動更新を妨げていると思います。おそらく、ビューCollectionChangedはコンストラクターでもサブスクライブするため、ビューがサブスクライブする前にイベントもサブスクライブし、refresh を呼び出すと、コレクションの変更とビュー自体の更新の間に不要な更新が行われます。

例えば

アイテム 0 が削除されます -> イベント リスナーに通知
=> ハンドラ: Refresh() -> ビューを再構築 => アイテムが削除されます。
=> ビュー ハンドラー: イベント引数 say: アイテム X が削除されました -> アイテム X を削除します

これは、最初と最後のアイテムが削除される理由をまだ説明していませんが、私には理にかなっているように思えます。

サブスクリプションがビューのインスタンス化の後である場合:

アイテム 0 が削除されました -> イベント リスナーに通知
=> ビュー ハンドラー: イベント引数の発言: アイテム X が削除されました -> アイテム X を削除
=> ハンドラー: Refresh() -> ビューを再構築 => 何も変更されていません。

于 2012-01-10T19:01:14.650 に答える
1

ListView の更新に問題があるようです。labe/TextBlock を ListView.Items.Count にバインドすると、(最初の削除後) リストにまだ 3 つの項目があることがわかります。

于 2012-01-10T19:21:51.290 に答える
-1

の新しいインスタンスを定義するために new キーワードを使用しないようにしてくださいlistCollectionView。代わりに以下を使用してください。

var sortedCities  = CollectionViewSource.GetDefaultView(Models);
于 2013-12-18T17:38:20.897 に答える