Итак, вот сценарий, у меня есть операция, которая очищает ObservableCollection, запускает запрос и повторно заполняет коллекцию результатами запроса.Эта коллекция привязана к списку.Вот пример: 500 результатов запроса приводят к серьезному времени обновления, которое блокирует пользовательский интерфейс из-за того, что воспринимается как «слишком длинный» (в действительности это составляет 0,5-2 секунды в большинстве систем). В любом случае, я знаю, что запрос достаточно быстрыйТак же, как и добавление элементов, я сузил его до уровня представления.
Проводя некоторое тестирование, я получаю заметно лучшую производительность, если удаляю шаблон элемента из списка (не очень), но не настолько лучше, чтобы он даже соответствовал ожиданиям, которые мне сообщили.Я обновил привязки так, чтобы они были применимыми, я изменил режим виртуализации на повторный цикл и убедился, что использую статические ресурсы, ни одно из вышеперечисленного не оказало заметного влияния на перерисовку.Мне было интересно, если у кого-нибудь есть хорошая идея, как улучшить производительность списка, заполненного большим количеством элементов?
<ListBox x:Name="listBox" Grid.Row="1" Grid.ColumnSpan="5" ItemsSource="{Binding SerialResults}" ItemTemplate="{StaticResource UnitHistoryTemplate}" BorderThickness="2" Grid.IsSharedSizeScope="True" VirtualizingStackPanel.VirtualizationMode="Recycling">
<DataTemplate x:Key="UnitHistoryTemplate">
<DataTemplate.Resources>
<DataTemplate x:Key="UnitFailureItemTemplate">
<Grid>
<TextBlock Margin="4,0,4,0" TextWrapping="Wrap" Text="{Binding}" Foreground="Red"/>
</Grid>
</DataTemplate>
</DataTemplate.Resources>
<Grid d:DesignWidth="580" d:DesignHeight="30" Background="#00000000">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="load"/>
<ColumnDefinition Width="Auto" SharedSizeGroup="run"/>
<ColumnDefinition Width="Auto" SharedSizeGroup="ser"/>
<ColumnDefinition Width="Auto" SharedSizeGroup="mot"/>
<ColumnDefinition Width="Auto" SharedSizeGroup="result"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="Load" Text="{Binding Load.LoadNumber, Mode=OneTime}" Margin="4,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" d:LayoutOverrides="HorizontalAlignment"/>
<TextBlock x:Name="Run" Text="{Binding Run.RunNumber, Mode=OneTime}" Margin="4,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" d:LayoutOverrides="HorizontalAlignment" Grid.Column="1"/>
<TextBlock x:Name="Serial" Text="{Binding Unit.SerialNumber, Mode=OneTime}" Margin="4,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" d:LayoutOverrides="HorizontalAlignment" Grid.Column="2"/>
<TextBlock x:Name="Mot" Text="{Binding Unit.MotString, Mode=OneTime}" Margin="4,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" d:LayoutOverrides="HorizontalAlignment" Grid.Column="3"/>
<TextBlock x:Name="Result" Text="{Binding Run.Result, Mode=OneTime}" Margin="4,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Column="4" d:LayoutOverrides="HorizontalAlignment, GridBox"/>
<ItemsControl ItemsSource="{Binding Unit.Failed, Mode=OneTime}" ItemTemplate="{StaticResource UnitFailureItemTemplate}" HorizontalAlignment="Left" Margin="4,0,0,0" Grid.Column="5">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Run.Result, Mode=OneTime}" Value="Aborted">
<DataTrigger.Setters>
<Setter TargetName="Result" Property="Foreground" Value="Red"/>
</DataTrigger.Setters>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
И так как об этом спрашивали несколько раз ниже, нет, это не так.моя наблюдаемая коллекция ... Я подавляю событие, выполняя пакет обновлений и переназначая источник элементов на новый экземпляр.
public async void FindUnitHistory()
{
if (IsCaching)
{
return;
}
else if (_serialSearch.Length <= MIN_SEARCH_LENGTH)
{
SerialResults.Clear();
return;
}
var newData = new ObservableCollection<UnitHistory>();
await TaskEx.Run(() =>
{
var results = from load in cache.LoadData.AsParallel()
from run in load.Runs
from unit in run.Units
where unit.SerialNumber.StartsWith(_serialSearch)
orderby run.RunNumber ascending
orderby load.LoadNumber descending
select new UnitHistory(load, run, unit);
foreach (var p in results)
{
newData.Add(p);
}
});
SerialResults = newData;
}