Проблемы с производительностью в столбцах ListView Resize (группирование) - программирование
Подтвердить что ты не робот

Проблемы с производительностью в столбцах ListView Resize (группирование)

У меня возникают основные проблемы с производительностью при ListView всякий раз, когда я реализую группировку. Я нашел несколько похожих вопросов в StackOverflow, но никто не помогает!


Вот моя текущая ситуация (я упростил свой проект, чтобы было меньше шума):

У меня есть ContentControl с ListView как ребенок. ListView привязан к ObservableCollection, который изначально пуст. По прошествии времени к коллекции добавляются объекты (в этом примере каждые 10 секунд добавляются 500 элементов с помощью DispatcherTimer). Размер ObservableCollection будет отличаться, но возможно, что коллекция может содержать более 25 000 элементов.

Если значение ObservableCollection меньше 2000 (не точная цифра), изменение размера столбца выглядит следующим образом:

enter image description here

Однако, поскольку в ObservableCollection добавлено больше объектов, наблюдается заметное снижение производительности (вам нужно прокрутить вниз, чтобы это произошло).

qD6R7.gif

Это приведет к блокировке Application.

Я думал, что проблема может быть решена с помощью Virtualization, поэтому я попытался использовать следующее:

<ListView x:Name="ListView1"
                  Style="{DynamicResource lvStyle}"
                  VirtualizingPanel.IsVirtualizingWhenGrouping="True"
                  VirtualizingPanel.IsVirtualizing="True"
                  VirtualizingPanel.IsContainerVirtualizable="True"
                  ScrollViewer.IsDeferredScrollingEnabled="True">

Однако ничего не работает!

Не говоря уже, VirtualizingPanel.IsVirtualizingWhenGrouping="True" заставляет ListView полностью блокировать.

Я также рассмотрел Пол МакКлин превосходную виртуализацию данных, однако он не обрабатывает группировку.


Вопрос: При группировке элементов в ListView существует ли способ изменить размер столбцов без существенного влияния на производительность приложения?

В идеале я хотел бы уменьшить накладные расходы памяти, поэтому я все для реализации своего рода асинхронного решения.


CODE:

XAML:

<ContentControl x:Class="ListViewDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
        xmlns:local="clr-namespace:ListViewDemo"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        xmlns:dat="clr-namespace:System.Windows.Data;assembly=PresentationFramework"
        xmlns:Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Classic" 
        mc:Ignorable="d" 
        d:DesignHeight="400" d:DesignWidth="300">
    <ContentControl.Resources>
    <Style x:Key="lvStyle" TargetType="{x:Type ListView}">
        <Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="True"/>
        <Setter Property="VirtualizingStackPanel.VirtualizationMode" Value="Recycling"/>
        <Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="True"/>
        <Setter Property="ListView.ItemsSource" Value="{Binding}"/>
        <Setter Property="ListView.View">
            <Setter.Value>
                <GridView>
                    <GridViewColumn Header="Name">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Name}"/>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="Date">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Date}"/>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="Desc">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Desc}"/>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                </GridView>
            </Setter.Value>
        </Setter>
        </Style>
    </ContentControl.Resources>

    <Grid>
        <ListView x:Name="ListView1"
                      Style="{DynamicResource lvStyle}"
                      VirtualizingPanel.IsVirtualizingWhenGrouping="True"
                      VirtualizingPanel.IsVirtualizing="True"
                      VirtualizingPanel.IsContainerVirtualizable="True"
                      ScrollViewer.IsDeferredScrollingEnabled="True">
            <ListView.GroupStyle>
                <GroupStyle>
                    <GroupStyle.ContainerStyle>
                        <Style TargetType="{x:Type GroupItem}">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type GroupItem}">
                                        <DockPanel>
                                            <Border DockPanel.Dock="Top">
                                                <TextBlock x:Name="groupItem"
                                                            Text="{Binding ItemCount, StringFormat={}({0} Results)}"></TextBlock>
                                            </Border>
                                            <ItemsPresenter DockPanel.Dock="Bottom"></ItemsPresenter>
                                        </DockPanel>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </GroupStyle.ContainerStyle>
                </GroupStyle>
            </ListView.GroupStyle>
        </ListView>
    </Grid>
</ContentControl>

КОД-ЗА:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace ListViewDemo
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : ContentControl
    {
        private ObservableCollection<Event> eventCollection = new ObservableCollection<Event>();

        public MainWindow()
        {
            InitializeComponent();

            DispatcherTimer dispatcherTimer = new DispatcherTimer();
            dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
            dispatcherTimer.Interval = new TimeSpan(0, 0, 10);
            dispatcherTimer.Start();

            ListView1.ItemsSource = eventCollection;
            ListView1.Items.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Descending));
            ListView1.Items.SortDescriptions.Add(new SortDescription("Date", ListSortDirection.Descending));
            ListView1.Items.GroupDescriptions.Add(new PropertyGroupDescription("Seconds"));
        }

        private void dispatcherTimer_Tick(object sender, EventArgs e)
        {
            for(var i = 0; i < 500; i++){
                eventCollection.Add(new Event
                {
                    Name = string.Format("Name_{0}", eventCollection.Count),
                    Date = DateTime.Now.ToString("MM.dd.yy HH:mm"),
                    Seconds = Convert.ToInt32(DateTime.Now.ToString("ss")),
                    Desc = "Description"
                });
            }
        }

        public class Event
        {
            public string Name { get; set; }
            public string Date { get; set; }
            public int Seconds { get; set; }
            public string Desc { get; set; }
        }

    }

}
4b9b3361

Ответ 1

Проблема с производительностью связана с тем, что вы не используете IsVirtualizingWhenGrouping

Вы упомянули, что использование IsVirtualizingWhenGrouping было блокировкой вашего приложения, и это известная проблема WPF (см. http://connect.microsoft.com/VisualStudio/feedback/details/780146/freeze-when-using-virtualizingpanel-isvirtualizingwhengrouping для получения дополнительной информации на этой ошибке происходит, когда пользовательский GroupStyle и IsVirtualizingWhenGrouping установлены в true)

Вот краткий рабочий вопрос, чтобы решить вашу проблему: вам просто нужно добавить расширитель в GroupStyle ControlTemplate. Затем вы сможете использовать IsVirtualizingWhenGrouping, а затем иметь хорошие характеристики при прокрутке/изменении столбцов.

Вот код, который работает на моей машине: (я поместил все непосредственно в MainWindow, чтобы немного упростить)

<Window x:Class="WpfApplication21.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>

        <Style x:Key="lvStyle" TargetType="{x:Type ListView}" >

            <Setter Property="ListView.ItemsSource" Value="{Binding}"/>
            <Setter Property="ListView.View">
                <Setter.Value>
                    <GridView>
                        <GridViewColumn Header="Name">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding Name}"/>
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                        <GridViewColumn Header="Date">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding Date}"/>
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                        <GridViewColumn Header="Desc">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding Desc}"/>
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                    </GridView>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>

    <Grid>
        <ListView x:Name="ListView1"
                  Style="{DynamicResource lvStyle}"
                  VirtualizingPanel.IsVirtualizing="True"
                  VirtualizingPanel.IsVirtualizingWhenGrouping="True">
            <ListView.GroupStyle>
                <GroupStyle>
                    <GroupStyle.ContainerStyle>
                        <Style TargetType="{x:Type GroupItem}">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type GroupItem}">
                                        <Expander IsExpanded="True">
                                            <DockPanel>
                                                <Border DockPanel.Dock="Top">
                                                    <TextBlock x:Name="groupItem"
                                                                Text="{Binding ItemCount, StringFormat={}({0} Results)}"></TextBlock>
                                                </Border>
                                                <ItemsPresenter x:Name="groupItemPresenter" DockPanel.Dock="Bottom"></ItemsPresenter>
                                            </DockPanel>
                                        </Expander>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </GroupStyle.ContainerStyle>
                </GroupStyle>
            </ListView.GroupStyle>
        </ListView>
    </Grid>
</Window>

РЕДАКТИРОВАТЬ: Вот контрольная таблица, которая "скрывает" расширитель. Это оригинальный, из которого я удалил ненужные части:

<ControlTemplate x:Key="CustomExpanderControlTemplate" TargetType="{x:Type Expander}">
        <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="3" SnapsToDevicePixels="True">
            <DockPanel>
                <ToggleButton x:Name="HeaderSite" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" DockPanel.Dock="Top" Foreground="{TemplateBinding Foreground}" FontWeight="{TemplateBinding FontWeight}" FontStyle="{TemplateBinding FontStyle}" FontStretch="{TemplateBinding FontStretch}" FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" MinWidth="0" MinHeight="0" Padding="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}">
                    <ToggleButton.FocusVisualStyle>
                        <Style>
                            <Setter Property="Control.Template">
                                <Setter.Value>
                                    <ControlTemplate>
                                        <Border>
                                            <Rectangle Margin="0" SnapsToDevicePixels="True" Stroke="Black" StrokeThickness="1" StrokeDashArray="1 2"/>
                                        </Border>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </ToggleButton.FocusVisualStyle>
                    <ToggleButton.Style>
                        <Style TargetType="{x:Type ToggleButton}">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type ToggleButton}">
                                        <Border Padding="{TemplateBinding Padding}">
                                            <Grid Background="Transparent" SnapsToDevicePixels="False">
                                                <Grid.ColumnDefinitions>
                                                    <ColumnDefinition Width="*"/>
                                                </Grid.ColumnDefinitions>
                                                <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Grid.Column="0" ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalAlignment="Left" Margin="4,0,0,0" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Center"/>
                                            </Grid>
                                        </Border>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </ToggleButton.Style>
                </ToggleButton>
                <ContentPresenter x:Name="ExpandSite" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" DockPanel.Dock="Bottom" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" Visibility="Collapsed" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
            </DockPanel>
        </Border>
        <ControlTemplate.Triggers>
            <Trigger Property="IsExpanded" Value="True">
                <Setter Property="Visibility" TargetName="ExpandSite" Value="Visible"/>
            </Trigger>
            <Trigger Property="ExpandDirection" Value="Right">
                <Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Right"/>
                <Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Left"/>
                <Setter Property="Style" TargetName="HeaderSite">
                    <Setter.Value>
                        <Style TargetType="{x:Type ToggleButton}">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type ToggleButton}">
                                        <Border Padding="{TemplateBinding Padding}">
                                            <Grid Background="Transparent" SnapsToDevicePixels="False">
                                                <Grid.RowDefinitions>
                                                    <RowDefinition Height="19"/>
                                                    <RowDefinition Height="*"/>
                                                </Grid.RowDefinitions>
                                                <Grid>
                                                    <Grid.LayoutTransform>
                                                        <TransformGroup>
                                                            <RotateTransform Angle="-90"/>
                                                        </TransformGroup>
                                                    </Grid.LayoutTransform>
                                                    <Ellipse x:Name="circle" Fill="Transparent" HorizontalAlignment="Center" Height="19" Stroke="DarkGray" VerticalAlignment="Center" Width="19"/>
                                                    <Path x:Name="arrow" Data="M1,1.5L4.5,5 8,1.5" HorizontalAlignment="Center" SnapsToDevicePixels="False" Stroke="#FF666666" StrokeThickness="2" VerticalAlignment="Center"/>
                                                </Grid>
                                                <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalAlignment="Center" Margin="0,4,0,0" Grid.Row="1" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Top"/>
                                            </Grid>
                                        </Border>
                                        <ControlTemplate.Triggers>
                                            <Trigger Property="IsChecked" Value="True">
                                                <Setter Property="Data" TargetName="arrow" Value="M1,4.5L4.5,1 8,4.5"/>
                                            </Trigger>
                                            <Trigger Property="IsMouseOver" Value="True">
                                                <Setter Property="Stroke" TargetName="circle" Value="#FF3C7FB1"/>
                                                <Setter Property="Fill" TargetName="circle" Value="Transparent"/>
                                                <Setter Property="Stroke" TargetName="arrow" Value="#FF222222"/>
                                            </Trigger>
                                            <Trigger Property="IsPressed" Value="True">
                                                <Setter Property="Stroke" TargetName="circle" Value="#FF526C7B"/>
                                                <Setter Property="StrokeThickness" TargetName="circle" Value="1.5"/>
                                                <Setter Property="Fill" TargetName="circle" Value="Transparent"/>
                                                <Setter Property="Stroke" TargetName="arrow" Value="#FF003366"/>
                                            </Trigger>
                                            <Trigger Property="IsEnabled" Value="False">
                                                <Setter Property="Stroke" TargetName="circle" Value="DarkGray"/>
                                                <Setter Property="Fill" TargetName="circle" Value="Transparent"/>
                                                <Setter Property="Stroke" TargetName="arrow" Value="#FF666666"/>
                                            </Trigger>
                                        </ControlTemplate.Triggers>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </Setter.Value>
                </Setter>
            </Trigger>
            <Trigger Property="ExpandDirection" Value="Up">
                <Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Top"/>
                <Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Bottom"/>
                <Setter Property="Style" TargetName="HeaderSite">
                    <Setter.Value>
                        <Style TargetType="{x:Type ToggleButton}">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type ToggleButton}">
                                        <Border Padding="{TemplateBinding Padding}">
                                            <Grid Background="Transparent" SnapsToDevicePixels="False">
                                                <Grid.ColumnDefinitions>
                                                    <ColumnDefinition Width="19"/>
                                                    <ColumnDefinition Width="*"/>
                                                </Grid.ColumnDefinitions>
                                                <Grid>
                                                    <Grid.LayoutTransform>
                                                        <TransformGroup>
                                                            <RotateTransform Angle="180"/>
                                                        </TransformGroup>
                                                    </Grid.LayoutTransform>
                                                    <Ellipse x:Name="circle" Fill="Transparent" HorizontalAlignment="Center" Height="19" Stroke="DarkGray" VerticalAlignment="Center" Width="19"/>
                                                    <Path x:Name="arrow" Data="M1,1.5L4.5,5 8,1.5" HorizontalAlignment="Center" SnapsToDevicePixels="False" Stroke="#FF666666" StrokeThickness="2" VerticalAlignment="Center"/>
                                                </Grid>
                                                <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Grid.Column="1" ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalAlignment="Left" Margin="4,0,0,0" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Center"/>
                                            </Grid>
                                        </Border>
                                        <ControlTemplate.Triggers>
                                            <Trigger Property="IsChecked" Value="True">
                                                <Setter Property="Data" TargetName="arrow" Value="M1,4.5L4.5,1 8,4.5"/>
                                            </Trigger>
                                            <Trigger Property="IsMouseOver" Value="True">
                                                <Setter Property="Stroke" TargetName="circle" Value="#FF3C7FB1"/>
                                                <Setter Property="Fill" TargetName="circle" Value="Transparent"/>
                                                <Setter Property="Stroke" TargetName="arrow" Value="#FF222222"/>
                                            </Trigger>
                                            <Trigger Property="IsPressed" Value="True">
                                                <Setter Property="Stroke" TargetName="circle" Value="#FF526C7B"/>
                                                <Setter Property="StrokeThickness" TargetName="circle" Value="1.5"/>
                                                <Setter Property="Fill" TargetName="circle" Value="Transparent"/>
                                                <Setter Property="Stroke" TargetName="arrow" Value="#FF003366"/>
                                            </Trigger>
                                            <Trigger Property="IsEnabled" Value="False">
                                                <Setter Property="Stroke" TargetName="circle" Value="DarkGray"/>
                                                <Setter Property="Fill" TargetName="circle" Value="Transparent"/>
                                                <Setter Property="Stroke" TargetName="arrow" Value="#FF666666"/>
                                            </Trigger>
                                        </ControlTemplate.Triggers>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </Setter.Value>
                </Setter>
            </Trigger>
            <Trigger Property="ExpandDirection" Value="Left">
                <Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Left"/>
                <Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Right"/>
                <Setter Property="Style" TargetName="HeaderSite">
                    <Setter.Value>
                        <Style TargetType="{x:Type ToggleButton}">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type ToggleButton}">
                                        <Border Padding="{TemplateBinding Padding}">
                                            <Grid Background="Transparent" SnapsToDevicePixels="False">
                                                <Grid.RowDefinitions>
                                                    <RowDefinition Height="19"/>
                                                    <RowDefinition Height="*"/>
                                                </Grid.RowDefinitions>
                                                <Grid>
                                                    <Grid.LayoutTransform>
                                                        <TransformGroup>
                                                            <RotateTransform Angle="90"/>
                                                        </TransformGroup>
                                                    </Grid.LayoutTransform>
                                                    <Ellipse x:Name="circle" Fill="Transparent" HorizontalAlignment="Center" Height="19" Stroke="DarkGray" VerticalAlignment="Center" Width="19"/>
                                                    <Path x:Name="arrow" Data="M1,1.5L4.5,5 8,1.5" HorizontalAlignment="Center" SnapsToDevicePixels="False" Stroke="#FF666666" StrokeThickness="2" VerticalAlignment="Center"/>
                                                </Grid>
                                                <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalAlignment="Center" Margin="0,4,0,0" Grid.Row="1" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Top"/>
                                            </Grid>
                                        </Border>
                                        <ControlTemplate.Triggers>
                                            <Trigger Property="IsChecked" Value="True">
                                                <Setter Property="Data" TargetName="arrow" Value="M1,4.5L4.5,1 8,4.5"/>
                                            </Trigger>
                                            <Trigger Property="IsMouseOver" Value="True">
                                                <Setter Property="Stroke" TargetName="circle" Value="#FF3C7FB1"/>
                                                <Setter Property="Fill" TargetName="circle" Value="Transparent"/>
                                                <Setter Property="Stroke" TargetName="arrow" Value="#FF222222"/>
                                            </Trigger>
                                            <Trigger Property="IsPressed" Value="True">
                                                <Setter Property="Stroke" TargetName="circle" Value="#FF526C7B"/>
                                                <Setter Property="StrokeThickness" TargetName="circle" Value="1.5"/>
                                                <Setter Property="Fill" TargetName="circle" Value="Transparent"/>
                                                <Setter Property="Stroke" TargetName="arrow" Value="#FF003366"/>
                                            </Trigger>
                                            <Trigger Property="IsEnabled" Value="False">
                                                <Setter Property="Stroke" TargetName="circle" Value="DarkGray"/>
                                                <Setter Property="Fill" TargetName="circle" Value="Transparent"/>
                                                <Setter Property="Stroke" TargetName="arrow" Value="#FF666666"/>
                                            </Trigger>
                                        </ControlTemplate.Triggers>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </Setter.Value>
                </Setter>
            </Trigger>
            <Trigger Property="IsEnabled" Value="False">
                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>

Вы можете использовать его, установив его в стиле группы:

<Expander IsExpanded="True" Template="{DynamicResource CustomExpanderControlTemplate}">

Ответ 2

Я думаю, что проблема заключается в ObservableCollection, которая привязана к вашему ListView, и к случаю, когда вы добавляете 500 элементов за добавление(). Каждый Add добавит 3 события. 2 NotifyPropertyChanged -Events для свойства Count и свойства Item[] и один NotifyCollectionChanged-Event коллекции, что подсчитывается до 1500 событий, которые были подняты.

Я обменялся ObservableCollection с моей собственной производной реализацией ObservableCollection, которая позволяет мне добавлять ряд элементов и вызывать только 3 события один раз.

    public class SmartCollection<T> : ObservableCollection<T> {
        public SmartCollection()
            : base() {

        }

        public SmartCollection(IEnumerable<T> collection)
            : base(collection) {

        }

        public SmartCollection(List<T> list)
            : base(list) {

        }

        public void AddRange(IEnumerable<T> range) {
            foreach (var item in range) {
                Items.Add(item);
            }

            this.OnPropertyChanged(new PropertyChangedEventArgs("Count"));
            this.OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
            this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }

        public void Reset(IEnumerable<T> range) {
            if (range == null) {
                throw new ArgumentNullException("range", "range is null");
            }

            var rangeToAdd = range.ToList();
            this.Items.Clear();

            AddRange(rangeToAdd);
        }
    }

Используя мою коллекцию, я изменил ваш метод, чтобы добавить элементы в коллекцию

private SmartCollection<Event> eventCollection = new SmartCollection<Event>();

private void dispatcherTimer_Tick(object sender, EventArgs e) {
  List<Event> newEvents = new List<Event>(500);

  for(var i = 0; i < 500; i++){
    newEvents.Add(new Event {
      Name = string.Format("Name_{0}", eventCollection.Count + i),
      Date = DateTime.Now.ToString("MM.dd.yy HH:mm"),
      Seconds = Convert.ToInt32(DateTime.Now.ToString("ss")),
      Desc = "Description"
    });
  }

  eventCollection.AddRange(newEvents);
}

Ответ 3

Я не уверен, подходит ли этот ответ, но я получил эту производительность после установки VirtualizingPanel.ScrollUnit свойство "Item". Проблема в том, что у меня было несколько визуальных сбоев, которые включали просмотр объекта Grouping, накладывающегося на верхнюю строку при прокрутке строки за строкой (колесиком мыши или клавишей вверх/вниз) и размыванием строк после прокрутки в качестве рендеринга удалили текст.

VirtualizingPanel.ScrollUnit="Item"

Изменить: Также измените VirtualizationMode на Standard, VirtualizingPanel.VirtualizationMode = "Стандарт", а визуальные глюки почти исчезнут. (Тестирование с 50 000 строк).