Виртуализация WrapPanel в виде ListT-ов ItemsTemplate
У меня есть ListView
в моем окне. ListView
по умолчанию ItemsPanel
был заменен на WrapPanel
, у меня тоже есть DataTemplate
ибо это ListViewItem
s. Во время выполнения главное окно не будет отвечать в течение некоторого времени, потому что ListView
иметь более 700 (и продолжать расти) ListViewItem
s (из привязки данных). Есть ли способ сохранить отзывчивость главного окна?
ДОПОЛНИТЕЛЬНО: когда ListView
не готов, я хочу текст (или ProgressBar
если возможно) покажитесь над ListView
и сказать что-то вроде "Пожалуйста, подождите..." или, может быть, "Загрузка элементов...".
XAML:
<ListView x:Name="MyListView" VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" HorizontalAlignment="Left" Height="577" VerticalAlignment="Top" Width="902" ScrollViewer.HorizontalScrollBarVisibility="Auto" Foreground="Black" Margin="10,10,0,0" ScrollViewer.CanContentScroll="True" BorderBrush="#FFC54B4B" BorderThickness="3" Background="White">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel MaxWidth="{Binding (FrameworkElement.ActualWidth),
RelativeSource={RelativeSource AncestorType=ScrollContentPresenter}}"
ItemWidth="{Binding (ListView.View).ItemWidth,
RelativeSource={RelativeSource AncestorType=ListView}}"
MinWidth="{Binding ItemWidth, RelativeSource={RelativeSource Self}}"
ItemHeight="{Binding (ListView.View).ItemHeight,
RelativeSource={RelativeSource AncestorType=ListView}}" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
РЕДАКТИРОВАТЬ:
Я попробовал это:
List<something> MyList = new List<something>();
ThreadPool.QueueUserWorkItem(_ =>
{
( Create MyList here...)
Dispatcher.BeginInvoke(new Action(() =>
{
MyListView.ItemsSource = MyList;
}));
});
Главное окно по-прежнему не отвечает, пока ListView не будет готов.
3 ответа
После поиска в Google в течение некоторого времени. Спасибо этой статье, Виртуализация WrapPanel не является невозможной! Вот как:
- Загрузите код отсюда
- Добавьте его в свой проект (В VS2010: Проект> Добавить существующий элемент)
Добавьте пространство имен в свой XAML:
xmlns:mwc="clr-namespace:MyWinCollection"
использование
VirtualizingWrapPanel
как твойListView
"sItemsTemplate
:<ListView x:Name="MyListView" ItemsSource="{StaticResource ItemCollection}"> <ListView.ItemsPanel> <ItemsPanelTemplate> <VirtualizingWrapPanel Orientation="Horizontal"/> </ItemsPanelTemplate> </ListView.ItemsPanel> </ListView>
Готово!
Поскольку не все элементы отображаются одновременно, главное окно теперь полностью адаптивно.
Надеется, что это поможет!: D
Кстати, спасибо, ребята! Вы, ребята, спасли мой день.
Вы используете панель (WrapPanel), которая не может выполнять виртуализацию пользовательского интерфейса (в отличие от VirtualizingStackPanel, который используется в шаблоне ListView ItemPanel по умолчанию). Это означает, что все ваши элементы отображаются, даже те, которые не видны в данный момент. Насколько я знаю, в WPF нет встроенной панели виртуализации, поэтому вы можете попробовать несколько бесплатных панелей виртуализации (пример - http://virtualwrappanel.codeplex.com/), но я не могу сказать, насколько они хороши, Я использую версию от Telerik, которая не является бесплатной. Другой вариант - переключиться обратно на VirtualizingStackPanel. В дополнение к этому, убедитесь, что вы загружаете свои элементы в не-пользовательский интерфейс (как упоминалось в другом ответе).
Если поток пользовательского интерфейса выполняет долгую операцию, он не сможет обрабатывать запросы пользовательского интерфейса. Это также известно как не отвечает. использование ThreadPool
как это:
private void operation_Click(object sender, RoutedEventArgs e)
{
ThreadPool.QueueUserWorkItem(_ =>
{
var result = LongTimeOperation();//set the operation in another thread so that the UI thread is kept responding
//use the Dispatcher to "return" to the UI thread
Dispatcher.BeginInvoke(new Action(() =>
{
//Use result
}));
});
}