wpf UI 在打开包含大量项目的 Combobox 时冻结

wpf UI freezes when opening Combobox with a large number of items

我正在开发一个 WPF 应用程序,其中有一个组合框,其中 ItemsSource 绑定到来自数据库的 属性 5000 条记录。问题是,当我单击组合框的下拉箭头时,UI 没有响应或组合框响应时间过长。我搜索了它,但对我没有任何帮助。

代码如下:

 <ComboBox IsEditable="True" ItemsSource="{Binding List,Mode=OneWay}" DisplayMemberPath="name" SelectedValue="{Binding SelectedItem,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
                                    <ComboBox.ItemsPanel>
                                        <ItemsPanelTemplate>
                                            <VirtualizingStackPanel VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling" />
                                        </ItemsPanelTemplate>
                                    </ComboBox.ItemsPanel>
                                </ComboBox>

和属性

  private ObservableCollection<Object> _List = new ObservableCollection<Object>();
        public ObservableCollection<Object> List
        {
            get { return _List ; }
            set { _List = value; OnPropertyChanged("List"); }
        }

编辑: 这是在构造函数中加载数据的代码

  public FormVM()
        {
              List = new ObservableCollection<Object>(db.cat.ToList());
        }

您必须启用 UI 虚拟化。

目前 UI 您的 ComboBox!

虚拟化被禁用

ListBoxListView 等控件默认启用此功能。
ComboBox 等扩展 ItemsControl 的其他控件必须明确启用它。

启用UI虚拟化

  1. ItemsControlItemsPresenter(或 Panel.IsItemsHost 设置为 True 的任何 Panel)必须是 ItemsControl 的子代ScrollViewer.
    ComboBox.

    已经是这种情况
  2. 必须将 ScrollViewer 配置为按项目(逻辑单位)而不是像素(物理单位)滚动,方法是将附加的 ScrollViewer.CanContentScroll 属性 设置为 True.

  3. ItemsControl 必须将其 ItemsPanel 设置为 VirtualizingStackPanel.

  4. 必须通过将附加的属性 VirtualizingPanel.IsVirtualizing设置为True来启用VirtualizingPanel的虚拟化模式。

例子

<ComboBox VirtualizingPanel.IsVirtualizing="True"
          ScrollViewer.CanContentScroll="True">
  <ComboBox.ItemsPanel>
    <ItemsPanelTemplate>
      <VirtualizingStackPanel />
    </ItemsPanelTemplate>
  </ComboBox.ItemsPanel>
</ComboBox>

可以通过启用延迟滚动来实现进一步的改进:

<ComboBox ScrollViewer.IsDeferredScrollingEnabled="True" />

满足以下条件之一将使UI无法虚拟化:

  • 物品容器直接添加到ItemsControl。例如, 如果应用程序明确地将 ListBoxItem 个对象添加到 ListBoxListBox 不虚拟化 ListBoxItem 个对象。

  • ItemsControl 中的物品容器有不同的类型。为了 例如,使用 Separator 对象的菜单无法实现项目 回收,因为菜单包含 Separator 类型的对象和 MenuItem.

  • CanContentScroll 设置为 false。

  • IsVirtualizing 设置为 false。

如果您遵循了所有约束,那么 UI 虚拟化就可以工作。然后,您遇到了与 UI 虚拟化无关的问题。如果您只使用 ComboBox 设置一个新的空项目,您应该不会遇到任何问题。