WPFでListboxにコンテンツ表示が異常に遅い

Listboxこんなに遅い?

WPFにListboxを配置し、その中のstackpanelにItemを表示していたらめちゃくちゃ遅くてとても使い物になりませんでした。

スクロールしようとしても遅いし、なにやっても遅いのです。

このプログラムのその部分は管理側しか使わない機能だったので、皆様にはごめんなさいして遅いまま使っていただいていたのですが、やっと解消しました。

解決報告

ここ数年の懸案だった分けですが、解決したので報告です。ただ、他の方とは、はまりポイントが違う気がするので参考になる方は少ないかも。

VertualizatingStackPanel

まず試したのは、Listbox内にVertualizatingStackPanelを配置して、見えていない部分はレンダリングしないという手法です。ただ疑念があったのは、私のプログラムはリストとしても200〜300程度。数千とか、数万のリスト表示をしているわけではないのです。

本家サイトから
https://docs.microsoft.com/ja-jp/dotnet/framework/wpf/advanced/optimizing-performance-controls

VertualizatingStackPanelオプションまとめ

こちらのサイトがとても参考になりました。

オプションを全部乗せしたXAMLが表示されていたので、それをコピペして真似して。だけど一向に変わりません。

また、仮想化の概念はこのサイトの方の絵が分かりやすいです。

VertualizatingStackPanelを利用したXAML

まずはVertualizatingStackPanelを利用したXAMLについて

<ListBox x:Name="listG" Margin="206,179,198,0" FontSize="26" BorderBrush="{x:Null}" ScrollViewer.VerticalScrollBarVisibility="Disabled" RenderTransformOrigin="0.5,0.5" Background="#FFFCFFDC"  ScrollViewer.HorizontalScrollBarVisibility="Disabled" Height="178" VerticalAlignment="Top" MouseUp="listG_MouseUp" ScrollViewer.CanContentScroll="True" ScrollViewer.IsDeferredScrollingEnabled="True" VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" ItemsSource="{Binding Collection}" ScrollViewer.PanningMode="HorizontalOnly">
                    <ListBox.RenderTransform>
                    <TransformGroup>
                        <ScaleTransform/>
                        <SkewTransform/>
                        <RotateTransform/>
                        <TranslateTransform/>
                    </TransformGroup>
                </ListBox.RenderTransform>
                <ListBox.ItemsPanel>
                    <ItemsPanelTemplate>
                        <VirtualizingStackPanel Orientation="Horizontal" CanHorizontallyScroll="True"/>
                    </ItemsPanelTemplate>
                </ListBox.ItemsPanel>

                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Grid Width="150" Background="{Binding Brush}" >
                            <Grid.RowDefinitions>
                                <RowDefinition Height="170" />
                            </Grid.RowDefinitions>
                            <Rectangle Grid.Row="0" />

                            <Rectangle Margin="2,2,2,2" Stroke="Black"/>
                             <TextBlock Margin="65,5,65,0" TextWrapping="Wrap" FontFamily="/Choose;component/Fonts/#HGPGyoshotai" FontSize="18"  TextAlignment="Center"><Run Language="ja-jp" Text="{Binding Name}"/></TextBlock>
                            <TextBlock Margin="75,5,55,0" TextWrapping="Wrap" FontFamily="/Choose;component/Fonts/#HGPGyoshotai" FontSize="18"  TextAlignment="Center"><Run Language="ja-jp" Text="{Binding Name1}"/></TextBlock>
                            <TextBlock Margin="55,5,75,0" TextWrapping="Wrap" FontFamily="/Choose;component/Fonts/#HGPGyoshotai" FontSize="18"  TextAlignment="Center"><Run Language="ja-jp" Text="{Binding Name2}"/></TextBlock>
                        </Grid>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

 

XAMLポイントitemsource

XAML itemsourceの引き渡し

ItemsSource="{Binding Collection}"

 

C#でList作成

C#表記では、Listをこのように引き渡しました

List GItemList = new List();
GItemData = new GItem { Name = dt.DefaultView[i]["name01"].ToString(), Color = TColor };
GItemList.Add(GItemData);
listG.ItemsSource = GItemList;

 

List化するクラス

GItemクラスは別途作成してあります

        public class GItem
        {
            public string Name { get; set; }
            public string Name1 { get; set; }
            public string Name2 { get; set; }
            public Color Color { get; set; }
            public Brush Brush
            {
                get { return new SolidColorBrush(Color); }
            }
            public Color FontColor { get; set; }
            public Brush FontBrush
            {
                get { return new SolidColorBrush(FontColor); }
            }
        }

 

結局遅かった原因

FontFamily="/Choose;component/Fonts/#HGPGyoshotai"

Textblockに指定したこのフォントが問題でした。このフォントはプログラムファイルを起動するフォルダに同梱してあります。このフォント指定をやめたら、Listboxが快適に動くようになりました。