Пользовательский интерфейс wpf зависает при открытии Combobox с большим количеством элементов - PullRequest
0 голосов
/ 13 июля 2020

Я работаю над приложением WPF, где у меня есть поле со списком с ItemsSource, привязанным к свойству 5000 записей, поступающих из базы данных. Проблема в том, что когда я нажимаю стрелку раскрывающегося списка поля со списком, пользовательский интерфейс не отвечает или поле со списком требует слишком много времени для ответа. Я искал его, но у меня ничего не получилось.

вот код:

 <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());
        }

1 Ответ

3 голосов
/ 13 июля 2020

Необходимо включить виртуализацию пользовательского интерфейса.

В настоящее время виртуализация пользовательского интерфейса отключена для ComboBox!

Элементы управления, такие как ListBox или ListView, по умолчанию имеют эту функцию. Другие элементы управления, расширяющие ItemsControl, например ComboBox, должны включать его явно.

Чтобы включить виртуализацию пользовательского интерфейса

  1. ItemsPresenter (или любой Panel с Panel.IsItemsHost установлен в True) из ItemsControl должен быть дочерним элементом ScrollViewer. Это уже имеет место для ComboBox.

  2. ScrollViewer необходимо настроить для прокрутки по элементам (логическим единицам) вместо пикселей (физических единиц), установив прикрепленные ScrollViewer.CanContentScroll на True.

  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" />

Выполнение одного из следующих условий сделает невозможной виртуализацию пользовательского интерфейса:

  • Контейнеры предметов добавляются непосредственно в ItemsControl. Например, если приложение явно добавляет ListBoxItem объекты в ListBox, ListBox не виртуализирует ListBoxItem объекты.

  • Контейнеры элементов в ItemsControl бывают разных типов. Например, Меню, в котором используются объекты Separator, не может реализовать повторное использование элементов, потому что Меню содержит объекты типа Separator и MenuItem.

  • Установка CanContentScroll на false.

  • Установка IsVirtualizing на false.

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

...