以下の記事では、連続的な描画をなめらかに行う、という「WPF」のパフォーマンス特性についてご紹介しました。
しかしながら、実際のアプリケーションにおいてユーザーがストレスを感じるような問題があっては使い物になりません。
WPFでよく知られているパフォーマンス上の問題として、データグリッドコントロールに大量のデータを表示させた場合に極端に縦方向のスクロールスピードが遅くなるという事象があります。今回はこの問題について、「Windows Forms」と比較しながら解説していきたいと思います。
- データグリッドに1,000行×100列のデータを表示
- データグリッドに10,000,000行×1列のデータを表示
- WPFの「UIの仮想化」
- 「UIの仮想化」の落とし穴
- WPFプラットフォームの優位性とは?
データグリッドに1,000行×100列のデータを表示
Windows Formsの標準コントロールである「DataGridView」コントロールにおいて、1,000行×100列=10万データをデータグリッドに連結させた場合、下の図のようにウィンドウサイズがそれほど大きくない条件下であれば、では非常に高速に縦方向のスクロールが行われます。
一方、同じデータをWPFのDataGridコントロールに表示させた場合、同一マシンで実行しているにもかかわらず、縦方向のスクロールスピードがマウスに追従しないほど遅くなり、動作がカクカクしてしまいます。
データグリッドに10,000,000行×1列のデータを表示
では、今度は10,000,000行×1列=1000万データをデータグリッドに連結させてみます。先ほどの10万データの100倍のデータ量です。この場合、WPFのDataGridでは非常に高速、かつなめらかにスクロールできます。
これに対して、Windows FormsのDataGridViewでは高速にスクロールさせた際に描画の更新頻度が極端に下がってしまい、画面がフリーズしたかのような表示になることがあります。
このような結果から、WPFのDataGridにおけるスクロールパフォーマンスは少なくとも単純なデータ量には依存していないことが分かります。また、列数に左右されるのではないかということも推測できるでしょう。
WPFの「UIの仮想化」
こちらの記事で説明したように、保持モードのグラフィックシステムを採用しているWPFでは、すべてのビジュアルオブジェクトはシリアル化され、描画データとして保持されています。
つまり、画面に表示されている行が10行であっても、実際のデータが1,000行であれば1,000行分の描画データが生成されていることになります。
このような問題を解決する方法として、実際に表示されている分のビジュアルオブジェクトのみを生成する「UIの仮想化」というテクニックがWPFには存在します。そして、WPFのDataGridコントロールの場合、既定では行方向にのみ「UIの仮想化」が適用されています。
100万行のデータを連結しても列数が1列であれば高速にスクロールできるのは、実際に表示されている約20行×1列=約20セル分のビジュアルオブジェクトだけが生成されるためです。
「UIの仮想化」が適用されているのは既定では行方向のみですが、列方向に対しても適用することが可能です。DataGridコントロールのEnableColumnVirtualization
プロパティを”True”に設定することで、100列表示した場合でも高速なスクロールを実現できます。
<Grid> <DataGrid x:Name="DataGrid1" EnableColumnVirtualization="True" /> </Grid>
なお、グレープシティが提供するグリッドコントロール「SPREAD for WPF(スプレッド)」の「GcSpreadGrid」の場合、行、列方向共に「UIの仮想化」は常に有効となっているので、特に設定を変更することなく、1,000行×100列のような大量のデータをなめらかにスクロールできます。
また、弊社の検証結果では、標準のDataGridよりもフレームレート(FPS)が高い数値となっており、よりなめらかなスクロールを実現しています。
「UIの仮想化」の落とし穴
ただし、「UIの仮想化」を行っている場合には注意が必要です。実際に画面に表示されている部分のビジュアルオブジェクトしか生成されないということは、すなわち表示されていない領域のセルをプログラムコードから参照することができないということです。
Windows FormsのDataGridViewコントロールでは、以下のようなコードで簡単に指定したセルの背景色を変更することができます。
dataGridView1[50, 50].Style.BackColor = Color.Red;
一方、WPFのDataGridコントロールで「UIの仮想化」を行方向、列方向ともに有効にした場合には、51行51列目のセルが画面上に表示されていない限りこのような操作を行うことはできません。
SPREAD for WPFのGcSpreadGridも、前述の通り、行、列方向共に「UIの仮想化」が常に有効となっていますが、このような問題をビジュアルオブジェクトから背景色や前景色といったスタイル情報を切り離して別に保持することで解決しています。
GcSpreadGridでは、以下のようなWindows Formsと同様のコーディングでセルにアクセスすることが可能です。
gcSpreadGrid1.Rows[50].Cells[50].Background = Brushes.Red;
WPFプラットフォームの優位性とは?
以下でWindowsデスクトップアプリケーション開発におけるWPFプラットフォームの優位性をまとめたページを公開しています。
今回少しだけ紹介した「SPREAD for WPF」を含め、WPFの開発を効率化するコンポーネントも多数紹介しているので、ぜひご覧ください。