2017-07-10 9 views
0

私のUWPアプリケーションで奇妙な問題が発生しています。 ObservableCollection<SomeInterface>にはListViewがバインドされています。私はObservableCollectionのすべてのアイテムの1つのプロパティを変更しています。問題は、ObservableCollectionがタイプ引数としてクラスを取らず、むしろinterfaceを受け取り、interfaceINotifyCollectionChangedを実装する方法を理解できないということです。プロパティの変更でListViewを更新する

私は先に進み、コレクション内のすべてのアイテムのプロパティを変更しました(INotifyPropertyChangedを実装せずに)。これは奇妙な行動を起こしています。私がプロパティを変更するとき(ListViewを含むページに移動するとすぐにこれを行います)ListViewに100個のアイテムがあり、最初のものが表示されている場合は、表示されていないアイテム10をスクロールせずに10の項目は変更されませんが、下にスクロールすると、他の(最初の10以外の)ListViewItemは変更が反映されています。そしてこれに加えて、私が(最初の10項目に)上にスクロールすると、今も変わっていることがわかります。

要約すると、現在表示されていない項目のみが更新されます。ここ

ObservableCollectionを更新するために私のコードです:

class SomePage : Page 
{ 
    private ObservabeCollection<SomeInterface> SomeObservableCollection { get; set; } = new ObservabeCollection<SomeInterface>(); 
    ... 
    private async Task ModifyObservableCollection() 
    { 
     var response = await MakeApiCall(); 
     var facets = response.ListOfItems; 

     foreach (var item in SomeObservableCollection.ToList()) 
     { 
      var fromApi = facets.author.FirstOrDefault(i => i.key == item.key); 
      if (fromApi == null) continue; 

      var itemInList = SomeList.FirstOrDefault(i => i.key == fromApi.key); 
      itemInList.read = fromApi.read; 
      itemInList.num = fromApi.num; 

      //here!! 
      itemInList = SomeObservableCollection.FirstOrDefault(i => i.key == fromApi.key); 
      itemInList.read = fromApi.read; 
      itemInList.num = fromApi.num; 
     } 
    } 
} 

これは私のListViewです:

<ListView ItemsSource="{x:Bind AuthorFacets, Mode=OneWay}" 
     ItemTemplate="{StaticResource ListViewDataTemplate}"       
     SelectionMode="Multiple"> 

      <ListView.ItemContainerStyle> 
       <Style TargetType="ListViewItem"> 
        <Setter Property="HorizontalContentAlignment" Value="Stretch" /> 
       </Style> 
      </ListView.ItemContainerStyle> 

</ListView> 

マイItemTemplateに:

<DataTemplate x:Key="ListViewDataTemplate" 
       x:DataType="local:ISomeInterface"> 
    <Grid> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="*"></ColumnDefinition> 
      <ColumnDefinition Width="Auto"></ColumnDefinition> 
     </Grid.ColumnDefinitions> 

     <TextBlock Text="{x:Bind read}"/>    
     <TextBlock Text="{x:Bind num}"/>    
    </Grid> 
</DataTemplate> 
+2

あなたは2つのことをする必要があります。まず、readおよびnumプロパティを所有するクラスでINotifyPropertyChangedを実装します(プロパティ値が変更されたときに実際にPropertyChangedイベントが発生します)。二番目に、 'Mode = OneWay'を' x:Bind'宣言に追加してください。なぜなら、デフォルトは 'OneTime'であるからです(あるいは' {Binding ...} 'に変更する)。 – Clemens

+1

'ListView'はデフォルトで仮想化をオンにしています。あなたは 'OneTime'バインディングを使用しているので、既に実現されているリストビュー項目は単に更新されません。しかし、実現しようとしているものについては、初めて新しいデータが入力されます。理にかなっている? –

+0

私は上下にスクロールすると、なぜこれは機能しますか? –

答えて

1

変更

<TextBlock Text="{x:Bind read}"/>    
<TextBlock Text="{x:Bind num}"/>  

<TextBlock Text="{x:Bind read, Mode=OneWay}"/>    
<TextBlock Text="{x:Bind num, Mode=OneWay}"/>  

とINotifyPropertyChangedのを実装する

、それが動作するはずです。デフォルトでは、x:バインドは従来のバインディング(パフォーマンス/メモリのため)とは異なりワンタイムです。したがって、表示されるアイテムは更新されません。

INPCなし?スクロール位置を失う可能性がありますが、プロパティを変更した後に親ビューでBindings.Update()を呼び出そうとする可能性があります。

+0

Bindings.Updateが機能しません。 –

関連する問題