【问题标题】:wpf UI freezes when opening Combobox with a large number of items打开包含大量项目的组合框时 wpf UI 冻结
【发布时间】:2020-07-13 12:43:15
【问题描述】:

我正在开发一个 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());
        }

【问题讨论】:

  • 请提供一个“可重现”的问题。这段代码运行速度快如闪电。
  • 是提前从数据库加载数据还是响应打开组合框?我们需要查看演示问题的代码。
  • @Erno 提前从数据库加载的数据。我在构造函数中加载了数据
  • @Bizhan 代码正在运行,但 UI 需要很长时间才能响应
  • 正如我所说,您的问题是“不可重现的”。所以对我们来说没有问题。一切都很好。如果我在 name 的 getter 上放置一个 thread.sleep,我会看到你解释的内容,但如果没有进一步的信息,我们无法帮助你

标签: c# wpf mvvm combobox


【解决方案1】:

您必须启用 UI 虚拟化。

目前为您的ComboBox 禁用 UI 虚拟化!

ListBoxListView 等控件默认启用此功能。
扩展 ItemsControl 的其他控件(如 ComboBox)必须显式启用它。

启用 UI 虚拟化

  1. ItemsControlItemsPresenter(或任何PanelPanel.IsItemsHost 设置为True)必须是ScrollViewer 的子代。
    ComboBox 已经是这种情况。

  2. 必须通过将附加的ScrollViewer.CanContentScroll 属性设置为True,将ScrollViewer 配置为按项目(逻辑单位)而不是像素(物理单位)滚动。

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

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

示例

<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 设置一个新的空项目,您应该不会遇到任何问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-15
    • 2015-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多