WPF - 在Listbox中绑定大量数据。

问题描述 投票:1回答:3

我正在创建一个书籍的搜索页面。数据库中有很多数据。如果数据大小超过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>
wpf data-binding listbox
3个回答
7
投票

应用程序显然是 "挂起 "的,因为数据加载发生在UI线程上。

你应该考虑一种不同的模式,使你能够在另一个线程中加载数据,并定期或在新数据到达时更新UI。

您可以使用一个 ObservableCollection 的事件。

后台加载线程更新集合,并向UI线程发出一个事件,表示需要更新。

这里有一个例子来说明如何在 GALA软体

您为该集合创建一个属性(在本例中为只读)。

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

然后在你的XAML中,

<ListBox ItemsSource="{Binding ElementName=mainWindow, Path=DataItems}"
         ...>
</ListBox>

2
投票

你可能会有一个问题,那就是你在ItemsPanelTemplate中使用了一个非虚拟化类型的面板(WrapPanel)。这意味着所有的2000个数据项将被加载,即使其中只有一小部分是可见的。默认情况下,ListBox使用VirtualizingStackPanel作为它的面板,正如其名称所示,它提供了虚拟化,所以它将只加载可见的数据集元素。

因此,在性能方面,一个简单的修复方法就是放弃WrapPanel,而使用一个虚拟化的面板,然而这显然会改变外观。

如果你特别想要一个WrapPanel,那么WPF并没有提供虚拟化的等价物,但是有一些实现,例如 http:/virtualwrappanel.codeplex.com。.


2
投票

试着用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>
© www.soinside.com 2019 - 2024. All rights reserved.