Optimizing Infragistics XamDataGrid Performance
XamDataGrid コンポーネントは、NetAdvantage for WPF 基幹業務製品 (無料試用版はこちらから入手可能) のコントロールの 1 つであり、WPF 製品で最も頻繁に使用されるコンポーネントです。表形式のデータを表示し、列のグループ化、並べ替え、フィルタリング、列の概要の計算、列のグループ化、並べ替え、ピン留めなどによるレイアウトの制御を行うことができます。
XamDataGrid コンポーネントは、NetAdvantage for WPF 基幹業務製品 (無料試用版はこちらから入手可能) のコントロールの 1 つであり、WPF 製品で最も頻繁に使用されるコンポーネントです。表形式のデータを表示し、列のグループ化、並べ替え、フィルタリング、列の概要の計算、列のグループ化、並べ替え、ピン留めなどによるレイアウトの制御を行うことができます。
XamDataGridは、リアルタイムのデータ更新と大量のデータを効率的に処理することもできます。このようなシナリオでは、XamDataGridのパフォーマンスは、アプリケーションの使いやすさにとって重要です。そのため、この投稿では、そのパフォーマンスを最大化するために何ができるかを見ていきます。
Built-In Optimizations
XamDataGridは、レコード レベルとセル レベルの両方でプレゼンター要素を再利用し、スタイル情報をキャッシュし、遅延ツールチップ スクロールを使用し、遅延オブジェクト作成を行うなど、さまざまな方法を内部で使用して最高のパフォーマンスを得られるようにします。パフォーマンスの最適化に関するより具体的な情報が利用可能です。ただし、これらの最適化はすべてすでに制御に組み込まれており、すぐに使用できます。
では、パフォーマンスを向上させるにはどのような方法があるのでしょうか?ここでは、使用を検討する可能性のあるポイントのリストをまとめましたが、そのほとんどがサンプル プロジェクトに実装されています。ここでは、これらの戦略がアプリケーションの外観や動作にどのように影響するかについて、できるだけ多くの情報を提供しようとしました。これにより、シナリオの特定の要件を検討し、どの要件を使用するかについて十分な情報に基づいた決定を下すことができます。
事前に書式設定された値へのバインド
読み取り専用カラムのパフォーマンスを向上させる方法の 1 つは、値のフォーマットを減らすことです。多くの場合、値の書式設定は、書式設定ロジックをカプセル化する簡単でクリーンな方法であるため、コンバーターを使用して実装されます。ただし、スクロールすると、グリッドによってセルが表示されるたびにコンバーター ロジックが呼び出されます。水平方向にスクロールして新しい列を表示すると、コンバーターは表示されている行の数と同じ回数だけ呼び出されます。この処理のオーバーヘッドは、リアルタイム更新を使用すると増加します。負荷を軽減する方法の 1 つは、コードで値の書式設定を実行し、グリッドを書式設定された結果 (1 回だけ計算される) にバインドすることです。さらに、遅延アプローチを使用すると、値を一度フォーマットしてからキャッシュできるため、基本的にUIによってフォーマットをトリガーする必要がなくなります。
たとえば、特定の方法でフォーマットしたい Price 値を持つ Product ビジネスオブジェクトがあるとします。これを行う 1 つの方法は、FormattedProduct を使用して元の Product を拡張し、要求時に計算され、後の要求のために格納される PriceFormatted プロパティを追加することです。一意の値の数が比較的少ない場合、このキャッシュ アプローチの領域要件をさらに減らす 1 つの方法は、書式設定された値にディクショナリを使用することです。
次に、これらの FormattedProducts の一覧にバインドしたら、Price 列が表示されないようにし、書式設定された値を表示する PriceFormatted 列のヘッダーを変更する必要があります。これは、FieldLayoutInitialized イベントのイベント ハンドラーで、Price 列の Visibility を Collapsed に設定し、PriceFormatted の Label プロパティを 'Price' に設定できます。
スタイリング
ホバーレススタイル
パフォーマンスを大幅に向上させるには、最も頻繁に使用される視覚要素に色付けやエフェクトを適用しないスタイルを設定する必要があります。そのような例の 1 つは、ホバーされている行に色を設定しないことです。高性能なXamDataGridホバーレススタイルをダウンロードしてください。もちろん、これらのスタイル プロパティの一部を引き続き使用したり、ニーズに合わせて変更したりすることもできます。このファイルをプロジェクトに追加し、次のように XamDataGrid から参照します。
<igDP:XamDataGrid.Resources> <ResourceDictionary Source="HoverlessStyles.xaml" /> </igDP:XamDataGrid.Resources>
Minimalist Styles
ビジュアル階層に何度も出現する要素 (CellValuePresentersなど) に対して独自のテンプレートを定義する場合は、できるだけ少ない要素を使用するようにしてください。テンプレートは、ビュー内のすべてのCellValuePresenterに対して初期化されるため、視覚要素の合計数が急速に増加し、パフォーマンスに悪影響を与える可能性があります。スタイルがパフォーマンスに与える影響については、より詳細な説明があります。最小の CellValuePresenter は、TextBlock を囲む Border で構成されます。ミニマリスト スタイルを使用する場合にパフォーマンスを向上させるために必要な重要な詳細は、ForceCellVirtualization プロパティ (11.1 の新機能) を true に設定することです。このミニマリスト スタイル ファイルをプロジェクトに追加し、次のように XamDataGrid から参照します。
<igDP:XamDataGrid.Resources> <ResourceDictionary Source="ReadOnlyHighPerformanceStyle.xaml" /> </igDP:XamDataGrid.Resources>
コントロールの包含が XamDataGrid のパフォーマンスに及ぼす影響
ビットマップ効果は、XamDataGrid を含むコントロールや XamDataGrid 要素では使用しないでください。しかし、このような効果は魅力的ですが、パフォーマンスには大きなコストがかかります。
XamDataGrid を StackPanel コントロールに配置すると、レコードを表示するための無限のサイズ領域があり、すべてのセルに対してCellValuePresentersがレンダリングされます。スクロールは外側のStackPanelによって正しく処理される場合がありますが、プレゼンターの数が多いため、メモリフットプリントは大きくなります。
テーマ設定
さまざまな要素に使用するテンプレートを決定するには、ある程度のオーバーヘッドが伴います。パフォーマンス上の利点は、次に示すように、デフォルトの Aero テーマであっても、使用するテーマを設定することで引き出すことができます。
<igDP:XamDataGrid Theme="Aero" />
FieldCollection の更新
データ プレゼンタに表示される要素を含むFieldLayoutの Fields コレクションにフィールドを追加または削除すると、パフォーマンスに悪影響を及ぼす可能性があります。コレクションに複数の変更を加える場合は、常にこれらの変更の前に BeginUpdate を呼び出し、変更後に EndUpdate を呼び出します。
抑制されたイベント
開発者がパフォーマンスを向上させる別の方法は、処理しないことがわかっているルーティング イベントを抑制することです。これにより、要素階層のルーティング イベントで発生するオーバーヘッドによるパフォーマンスが向上します。また、DataPresenterBase の一般的なルーティング イベントに対して直接 CLR イベントも追加されています。ルーティング イベントの名前の後に "Direct" が付けられた名前が付けられます (例: "CellActivatedDirect" ルーティング イベントの場合)。これにより、ルーティング イベントを抑制しながら、直接同等のイベントを処理できます。
イベントを抑制するには、サンプル プロジェクトに実装されている DataPresenterBase.SuppressedEvents コレクションにイベントを追加し、次に示すように、イベントを追加します。
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:igDP="http://infragistics.com/DataPresenter" xmlns:igED="http://infragistics.com/Editors" Title="Window1" Height="600" Width="800"> <Grid> <igDP:XamDataGrid> <igDP:XamDataGrid.SuppressedEvents> <igDP:RoutedEventWrapper RoutedEvent="igED:ValueEditor.TextChanged" /> … <igDP:RoutedEventWrapper RoutedEvent="igED:ValueEditor.ValueChanged" /> </igDP:XamDataGrid.SuppressedEvents> </igDP:XamDataGrid> </Grid> </Window>
レコード・サイジング・モード
FieldLayoutSettings.DataRecordSizing モード プロパティは、XamDataGrid 内のレコードのサイズとサイズ変更の方法を制御します。このプロパティは、各行のサイズを個別に設定するか、行の高さを等しくするかを制御するため、パフォーマンスに影響します。
このプロパティの Fixed 値と SizableSynchronized 値を指定すると、行の高さは等しくなります。XamDataGrid は、レイアウト操作中に追加のリソースを必要とする異なる高さの行よりも速く等高さの行をレイアウトできるため、これら 2 つの設定には最大のパフォーマンス上の利点があります。
FieldLayoutSettings.DataRecordSizing の SizedToContentAndFixed 値と SizedToContentAndIndividuallySizable 値により、行のサイズが異なる場合があります。これらの設定では、レイアウトにある程度の柔軟性がありますが、レイアウトに追加のリソースが必要になるため、スクロール時の XamDataGrid のパフォーマンスに悪影響を及ぼします。
Setting Scrolling Mode
XamDataGridの既定の Thumb スクロール動作は、表示されるレコードの列の値 (IsScrollTipFieldプロパティを使用して指定可能) を含むツールヒントを使用した遅延スクロールです。これにより、現在のレコード列の値を探すためにスクロールを一時停止するのではなく、特定の列の値を使用して探しているレコードをすばやく見つけることができます。
即時スクロールを有効にするには、ScrollingModeプロパティを Immediate に設定します。遅延スクロールとは異なり、即時スクロールでは、対応するスクロール位置のレコード全体が表示されている必要があります。このアプローチでは、多くの視覚要素が連続して操作され、パフォーマンスに悪影響を及ぼします。このため、特に要件がない限り、即時スクロールモードの使用はできるだけ控えてください。
Adjusting Cell Presenter Virtualization
XamDataGridがレコードとセルのプレゼンターを仮想化する方法を制御するには、RecordContainerGenerationMode プロパティと CellContainerGenerationMode プロパティを設定します。さまざまな仮想化戦略、それらの空間と時間への影響、およびそれらが役立つシナリオについて説明します。
リサイクル
デフォルトでは、XamDataGridは使用するプレゼンターをリサイクルします – 表示されているレコード/セルのプレゼンターのみを初期化し、ビューがスクロールされるときに再利用されます。このキャッシュ モードは、データの一般的な参照に最適化されており、メモリ フットプリントを最小限に抑えながら、時間の側面を犠牲にしています。このアプローチはメモリを節約し、ほとんどの場合にうまく機能しますが、特に複雑な要素階層を含むXamDateTimeEditorなどのエディターでは、スクロールが完全ではない可能性があります。
PreLoad
XamDateTimeEditorsなどの複雑なエディターを含む多数の列があり、余分な列を表示するために水平スクロールをすばやく行う必要があるシナリオを想像してみましょう。XamDataGridは、PreLoad 戦略を使用して、表示するすべてのセルのプレゼンターを初期化し、スムーズなスクロール エクスペリエンスを確保します。ただし、初期読み込み時間とメモリ フットプリントが増加します。PreLoad 設定は、行数が比較的少ないシナリオ (RecordContainerGenerationMode 設定時) または列数 (CellContainerGenerationMode 設定時) に適しているため、読み込み時間とメモリ使用量が目立つ可能性があります。
LazyLoad
比較的少量のレコードと大量の列があり、ユーザーが常にすべての列に目を通すとは限らないシナリオを実装している場合があります。この場合、メモリ使用量を最小限に抑えながら、既に表示されている列のスクロール速度を良好に保つには、プレゼンターを一度だけ初期化し (表示したとき)、2 回目に表示したときのスクロールを改善するためにキャッシュします。この結果、初期読み込み時間が短くなり、XamDataGridの読み込み以降に表示されたすべてのセルのプレゼンターを含むメモリ フットプリント (PreLoad ストラテジーの場合のように、すべてではありません) が発生し、セルが初めて表示されるときにのみスクロール パフォーマンスが低下します。同じセルを 2 回目に表示することは、プレゼンターが最初に表示されたときにキャッシュされるため、高速になります。
Hierarchies
パフォーマンスを向上させるために、XamDataGridはデフォルトで親レコードと子レコードを表示するために 1 つのパネルを使用します。これには、次の欠点があります。
- ネストされたレコードはクロムで囲まれていません
- ネストされたレコードを処理するRecordPresenterオブジェクトのテンプレート内のトリガーは無視されます
- ネストされたレコードを処理する RecordPresenter オブジェクトのテンプレート内のアニメーションは無視されます
上記の機能のいずれかを使用する場合は、GridViewSettingsの UseNestedPanels プロパティを true に設定することで、入れ子になった複数のパネルを使用できます。階層レコードとパフォーマンスに関する追加情報が利用可能です。
概要
このブログ記事では、XamDataGridのパフォーマンスを微調整するいくつかの方法を見てきました。次回アプリケーションを構築するときは、テーマ、スタイル要件、メモリと時間の制約を念頭に置いて、これらを検討して使用してください。