Диагностика проблем производительности с привязкой к данным WPF ComboBox - PullRequest
5 голосов
/ 21 сентября 2010

Я боролся с "медленным" ComboBox WPF этим утром, и хотел бы посмотреть, есть ли у кого-нибудь советы по устранению такой проблемы.

Допустим, у меня есть два ComboBox, A и B. КогдаA меняется, элементы в B также меняются.Каждый из ComboBox имеет свою привязку данных SelectedItem и ItemsSource следующим образом:

<ComboBox Grid.Column="1" ItemsSource="{Binding Names}" SelectedItem="{Binding CurrentName, Mode=TwoWay}" Margin="3" MinWidth="100" />
<ComboBox Grid.Column="1" Grid.Row="1" ItemsSource="{Binding SubNames}" SelectedItem="{Binding CurrentSubName, Mode=TwoWay}" Margin="3" MinWidth="100" />

Всякий раз, когда необходимо изменить список в B, я делаю это, удаляя SubNames и затем повторно добавляя записи на основе SelectedItem в A.Это сделано потому, что перезапись SubNames новым ObservableCollection<string> нарушает привязку данных.

Все на одном компьютере работает так, как вы ожидаете.Выберите A, затем нажмите B, и сразу появятся новые элементы.На другом компьютере, когда я это делаю, перед рендерингом ComboBox возникает пауза 5 секунд .Количество предметов точно такое же.Единственное отличие состоит в том, что на медленной машине в фоновом режиме происходит аппаратная связь.Я заморозил все эти темы, и это не помогло.

Моя самая большая проблема заключается в том, что я не могу понять, где даже начать искать.Мне нужно посмотреть, что делает система в тот момент, когда нажимается ComboBox.Я использую привязку данных, поэтому нигде не могу поставить точку останова.Я попытался изменить свое объявление SubNames с

public ObservableCollection<string> SubNames { get; set; }

на

private ObservableCollection<string> subnames_ = new ObservableCollection<string>();
public ObservableCollection<string> SubNames
{
  get { return subnames_; }
  set { subnames_ = value; }
}

и затем установил точки останова в получателе и установщике, чтобы увидеть, происходит ли чрезмерное чтение или запись,но не было никаких.

Кто-нибудь может предложить мне следующий шаг, чтобы попытаться определить источник этого замедления?Я не верю, что это имеет какое-либо отношение к шаблону ComboBox, как описано в этой статье .

1 Ответ

2 голосов
/ 21 сентября 2010

Хотя это может не дать прямого ответа на ваш вопрос, одно из предложений состоит в том, чтобы не связываться напрямую с ObservableCollection. Поскольку коллекция может вызывать много событий при манипулировании своим содержимым, лучше связать ItemsControl с ICollectionView, который представляет этот ObservableCollection, а при обновлении коллекции использовать ICollectionView.DeferRefresh().

Обычно я делаю класс, производный от ObservableCollection, который предоставляет свойство DefaultView, которое лениво создает экземпляр ICollectionView, соответствующий коллекции. Затем я связываю все ItemsControls со свойством collection.DefaultView. Затем, когда мне нужно обновить или иным образом манипулировать элементами в коллекции, я использую:

using (collection.DefaultView.DeferRefresh()) {
  collection. // add/remove/replace/clear etc
}

Это обновляет связанные элементы управления только после удаления объекта, возвращенного DeferRefresh().

Также имейте в виду, что механизмы связывания в WPF имеют TraceSource по умолчанию, который можно использовать для получения дополнительной информации о самих привязках; оно не отслеживает время, поэтому я не уверен, насколько это полезно, но вы можете активировать его с помощью:

System.Diagnostics.PresentationTraceSources.DataBindingSource.Switch.Level = System.Diagnostics.SourceLevels.Verbose;

(или любой другой уровень, который вы предпочитаете).

...