2017-02-16 8 views
2

INotifyCollectionChangedを実装するカスタムコレクションを作成しようとしています。これは大きなプロジェクトの一部ですが、私はこの問題を示すサンプルアプリケーションを作成することができました。INotifyCollectionChangedが一括変更を報告すると、UWPのListViewに予期しない動作が発生する

1)ビジュアルスタジオ2015を開き、Build 14393を使用してBlank Universal Windowsアプリを作成し、同じ名前空間を持つように「SampleApp」と呼んでください。

2)Main.xaml

<Page x:Class="SampleApp.MainPage" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:local="using:SampleApp" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     mc:Ignorable="d"> 

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
     <ListView ItemsSource="{x:Bind Items}" Margin="40"/> 
    </Grid> 
</Page> 

3に次のコードをコピー)Main.xaml.csに次のコードをコピー:

using System.Collections.Generic; 
using System.Collections.Specialized; 
using System.ComponentModel; 
using System.Threading.Tasks; 
using Windows.UI.Xaml; 

namespace SampleApp 
{ 
    public sealed partial class MainPage 
    { 
     public FakeCollection Items { get; } = new FakeCollection(); 

     public MainPage() 
     { 
      InitializeComponent(); 

      Loaded += OnLoaded; 
     } 

     private async void OnLoaded(object sender, RoutedEventArgs e) 
     { 
      await Items.Begin(); 
     } 
    } 

    public class FakeCollection : List<string>, INotifyCollectionChanged, INotifyPropertyChanged 
    { 
     public event NotifyCollectionChangedEventHandler CollectionChanged; 
     public event PropertyChangedEventHandler PropertyChanged; 


     public async Task Begin() 
     { 
      var set1 = CreateSet(1, 10); 
      var set2 = CreateSet(11, 15); 

      AddRange(set1); 

      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Count")); 
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Item[]")); 
      CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, set1, 0)); 


      await Task.Delay(2000); 

      InsertRange(5, set2); 

      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Count")); 
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Item[]")); 
      CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, set2, 5)); 
     } 

     public List<string> CreateSet(int start, int end) 
     { 
      var list = new List<string>(); 

      for (var i = start; i <= end; i++) 
      { 
       list.Add($"Item {i}"); 
      } 

      return list; 
     } 
    } 
} 

FakeCollectionだけList<string>INotifyPropertyChangedINotifyCollectionChangedを実装します。これはxamlのListViewバインディングで使用されます。

Begin()メソッドが呼び出され、 "Item 1"、 "Item 2"、... "Item 10"という文字列のリストが作成され、リストに追加され、通知されます全10項目のコレクション変更。これは正常に動作します。

ただし、2秒待ってから別のセットが「アイテム11」、「アイテム12」、「アイテム15」に作成され、インデックス5に挿入されます。コレクションの変更は位置5新しい文字列で置き換えます。

項目1,2,3,4,5,11,12,13,14,15:

私はあるFakeCollectionの内部コレクションに見つかり正確な順序を示すためにListViewを期待します、6,7,8,9,10

代わりに、それは

項目1,2,3,4,5,11,6,7,8,9,10,7として表示され、 8,9,10 ????

ここで何が起こりましたか?それは、盛り上がったイベントの最初のアイテムを追加したように見え、最後の4つを繰り返したようです!

ListViewをバルクコレクションの変更に使用するためのトリックはありますか?

答えて

1

興味深い!一度に複数の項目を追加しようとすると、CollectionChangedのように見えません。残念ながら、これは単に標準の ``のObservableCollection にそれを回すだろう

for (var i = 0; i < set2.Count; i++) 
{ 
    CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, set2, i + 5)); 
} 
+0

- 私はあなたがこのような何かを行う必要がありますね。理想的ではない。 Microsoftに報告します。 – Laith

+0

実際WPF以来このようになっているようです。彼らが行動を変えるとは思わないでください。 –

関連する問題