WPF - привязка большого количества данных в списке - PullRequest
1 голос
/ 12 октября 2010

Я создаю страницу поиска для книг.В базе данных отсутствуют данные.Если размер данных превышает 2000, приложение зависает.ItemsSource списка, в котором есть данные, но за ними что-то не так.

Код

 <ListBox Grid.Column="1" 
          x:Name="lbResult"  
          ItemsSource="{Binding}"   
          SelectionChanged="lbResult_SelectionChanged">
    <ListBox.ItemTemplate>
         <DataTemplate>
            <StackPanel Width="320">
                <TextBlock Margin="10">
                   <InlineUIContainer>
                       <TextBlock Foreground="DarkKhaki" Text="{Binding Title}"/>
               </InlineUIContainer>
                   <Run Text=" "/><LineBreak/>
                   <InlineUIContainer>
                       <TextBlock Text=" By "/>
               </InlineUIContainer>
                   <Run Text=" "/>
                   <InlineUIContainer>
                       <TextBlock Text="{Binding Author}"/> 
               </InlineUIContainer>
                </TextBlock>
            </StackPanel>
         </DataTemplate>
    </ListBox.ItemTemplate>
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel IsItemsHost="True" Orientation="Vertical"/>
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
</ListBox>

Ответы [ 3 ]

7 голосов
/ 12 октября 2010

Приложение явно «зависает», потому что загрузка данных происходит в потоке пользовательского интерфейса.

Следует рассмотреть другую модель, которая позволяет загружать данные в другой поток и периодически обновлять пользовательский интерфейс или каки когда поступают новые данные.

Вы можете использовать для этого ObservableCollection.

Поток фоновой загрузки обновляет коллекцию и запускает событие в пользовательском интерфейсе.поток, указывающий, что требуется обновление.

Есть пример того, как это сделать на GALA Soft

Вы создаете свойство (только для чтения в этом случае) дляколлекция:

private ObservableCollection<MyDataItem> dataItems;
public ObservableCollection<MyDataItem> DataItems
{
      get { return dataItems; }
}

Тогда в вашем XAML:

<ListBox ItemsSource="{Binding ElementName=mainWindow, Path=DataItems}"
         ...>
</ListBox>
2 голосов
/ 27 апреля 2012

Попробуйте использовать ListView, у меня была та же проблема. Теперь я могу загрузить более 7000 предметов в одно мгновение.

Как это:

  <StackPanel Grid.Row="1" Grid.Column="0">
      <ListView 
           Height="100"
           Name="lstPlayerList">
           <ListView.View>
                <GridView>
                     <GridViewColumn 
                         Width="100"           
                         Header="LastName"
                         DisplayMemberBinding="{Binding LastName}">
                     </GridViewColumn>
                 </GridView>
           </ListView.View>
       </ListView>
   </StackPanel>
2 голосов
/ 15 марта 2012

Одна из проблем, с которой вы можете столкнуться, заключается в том, что вы используете не виртуализирующий тип панели (WrapPanel) в вашем ItemsPanelTemplate.Это означает, что все 2000 элементов данных будут загружены, даже если видна только часть из них.По умолчанию ListBox использует VirtualizingStackPanel в качестве своей панели, которая, как следует из названия, обеспечивает виртуализацию, поэтому она будет загружать только видимые элементы набора данных.

Таким образом, простое исправление с точки зрения производительности - обойтись безВместо этого WrapPanel и мы использовали панель виртуализации, однако это, очевидно, изменит внешний вид.

Если вы особенно хотите WrapPanel, то в WPF нет виртуализированного эквивалента, но есть реализации, такие как http://virtualwrappanel.codeplex.com/.

...