ListView
グループ化を実装するたびに、重大なパフォーマンスの問題が発生します。StackOverflow で似たような質問を見つけましたが、役に立たないようです。
これが私の現在の状況です(ノイズが少ないようにプロジェクトを簡素化しました):
私は を子供としてContentControl
持っています。ListView
は、最初は空である にListView
バインドされます。ObservableCollection
時間が経過すると、オブジェクトがコレクションに追加されます (この例では、 を使用して 10 秒ごとに 500 個のアイテムが追加されますDispatcherTimer
)。サイズはObservableCollection
さまざまですが、コレクションが最終的に 25,000 点を超える可能性があります。
ObservableCollection
が 2000 未満の場合 (正確な数値ではありません)、列のサイズ変更は次のようになります。
ただし、 にオブジェクトを追加するとObservableCollection
、パフォーマンスが著しく低下します (これを行うには、下にスクロールする必要があります)。
これは最終的に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
Paul McClean の優れた Data Virtualizationも調べましたが、グループ化は処理されません。
質問: で項目をグループ化する場合ListView
、アプリケーションのパフォーマンスに大きな影響を与えずに列のサイズを変更する方法はありますか?
理想的には、メモリのオーバーヘッドを減らしたいので、ある種の非同期ソリューションを実装することに賛成です。
コード:
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; }
}
}
}