WPF Listview - Выберите элементы за пределами "поля зрения"
Я использую ListView, чтобы показать элементы в списке. Пользователь может сам выбирать элементы или использовать некоторые "ключи предварительного выбора" для выбора элементов с заданными атрибутами.
Для проверки предметов я использую что-то подобное:
for(int i;i<MyListView.Items.Count;++i)
{
if( /*... Check if the items should be selected ...*/ )
(MyListView.ItemContainerGenerator.ContainerFromIndex(i) as ListViewItem).IsSelected = true;
}
Это прекрасно работает для предметов, которые видны во время исключения. Но для элементов, которые не видны, ContainerFromIndex() возвращает ноль. Я слышал, что это как-то связано с виртуализацией, и что Список не знает об элементах "вверх" или "вниз" "поля зрения". Но как получается, что выбранные элементы в списке могут быть вне поля зрения, когда вы выбираете их вручную?
А как сделать выбор предмета за пределами "поля зрения"? Я думаю, что это должно быть возможно.
Спасибо за любую помощь, Маркс
2 ответа
Как вы упомянули, я предполагаю, что проблема заключается в виртуализации элементов ListView. По умолчанию ListView (и ListBox) используют VirtualizingStackPanel
как их ItemsPanel для улучшения производительности. Краткое объяснение того, как это работает, можно прочитать здесь.
Однако вы можете заменить другую панель. В этом случае попробуйте использовать обычный StackPanel. Если у вас есть множество элементов в ListView, особенно если это сложные элементы, производительность может немного снизиться.
<ListView>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
редактировать
Вы также можете попробовать решение, описанное в этом похожем вопросе, в зависимости от вашей модели. Тем не менее, это, вероятно, не будет работать для вас.
При работе с элементами управления виртуализацией альтернативой отключению виртуализации (которая иногда бывает полезной, даже если она мешает правильной работе других частей API) является поиск VirtualizingPanel
и скажи это явно для прокрутки.
Например:
void ScrollToIndex(ListBox listBox, int index)
{
VirtualizingPanel panel = FindVisualChild<VirtualizingPanel>(listBox);
panel.BringIndexIntoViewPublic(index);
}
static T FindVisualChild<T>(DependencyObject o) where T : class
{
T result = o as T;
if (result != null)
{
return result;
}
int childCount = VisualTreeHelper.GetChildrenCount(o);
for (int i = 0; i < childCount; i++)
{
result = FindVisualChild<T>(VisualTreeHelper.GetChild(o, i));
if (result != null)
{
return result;
}
}
return null;
}
Я не очень доволен необходимостью поиска по визуальному дереву, чтобы найти панель, но я не знаю ни другого способа получить ее, ни прокрутки до определенного индекса при работе с панелью виртуализации.