MESCIUS SPREAD for Windows Forms 15.0J > 開発者ガイド > SPREADコントロール > レイアウトの一時停止によるパフォーマンスの向上 |
コントロールのパフォーマンスを向上させる手段として、多数のセルに変更があった場合に、すべての変更が完了するまで再描画を保留する方法があります。すべての変更と再計算が完了するまで再描画を保留(レイアウトへの反映を一時停止)してから、レイアウトを再開し、すべてのセルを一括して再描画することで、コンポーネントの処理時間を大幅に短縮しつつ、適切に更新されたインタフェースをユーザーに提供できます。
以下、レイアウト、およびその一時停止について説明します。
レイアウトは、コンポーネントを現在の状態に描画するためのさまざまな計算値(主にセルの幅や高さ、結合セル、ビューポート)を保持するオブジェクトです。このオブジェクトには、現在のビューポート数、各ビューポートの左上隅のセルについての情報、各列や各行のサイズ、各ビューポートで現在表示されている行数や列数といった情報が保持されます。レイアウトオブジェクトの目的は、コンポーネントの描画を最適化することです。具体的には、描画中に使用したレイアウト用の計算値を保存して、コンポーネントを再描画するたびにこれらを再利用します。これにより、レイアウト値を毎回再計算する必要がなくなります。レイアウトオブジェクトの再生成が必要となる変更が検出された場合は、既存のオブジェクトが破棄され、描画コードによって新規のレイアウトオブジェクトが計算されます。レイアウトオブジェクトはパブリックAPIの一部ではありませんが、シートの描画に必要なあらゆるレイアウト情報をキャッシュします。たとえば、列幅、行高、結合セル、セルのオーバーフロー表示、常時表示されるセルノート領域(CellオブジェクトのNoteStyleプロパティがStickyNoteに設定されている場合)などの情報です。
レイアウトを一時停止すると、パフォーマンスを向上させることができます。これはレイアウトオブジェクトの更新を停止する処理であり、レイアウトが再開されるまで、コンポーネントは再描画のための計算をいっさい行わなくなります。 これには、FpSpreadクラスのSuspendLayoutおよびResumeLayoutメソッドを使用します。この2つのメソッドは、特定の処理スコープ内で、必ず2つ1組で使用するようにしてください。そうしないと、一時停止されたレイアウトが再開されないという問題が発生する可能性があります。
SuspendLayoutメソッドはシートに変更が加えられた場合に、列、行、およびセルのレイアウトの再計算を一時停止します。 1つのコードブロック内でシートに大量の変更を加える場合は、SuspendLayoutを使用することで、個々の変更が加えられるたびにレイアウトオブジェクトを再計算する冗長な中間処理を排除できます。すべての変更が完了した後でResumeLayout(true)を実行すると、レイアウトが一括して再計算されます。これだけでもパフォーマンスを大幅に向上できますが、シートに必要な機能に応じて、さらに処理を効率化することもできます(後述の「その他のパフォーマンス向上方法」を参照してください)。
レイアウトが一時停止された後、これに対応する再開メソッドが同一スコープ内で実行されずに例外が発生した場合は、レイアウトが一時停止中であることを通知するメッセージが表示されます。また、コンポーネントの状態が変更され、それまでレイアウトオブジェクトに保持されていたデータが無効になると(不適切な数値など)、この無効なレイアウトデータによってコンポーネントが描画を試みた際に、例外が発生する可能性があります。一時停止の通知は、コントロールの描画中に処理不能な例外が発生し、この例外の発生時にレイアウトが一時停止されている場合に表示されます。
この問題が発生するのは、SuspendLayoutによってレイアウトを一時停止してからコンポーネントの状態を変更した際に、何らかの理由で、無効なレイアウトオブジェクトによって描画が再開された場合のみです。このメッセージの表示は、レイアウトの一時停止とは無関係の例外が原因である場合もあります。たとえば、IRenderer.PaintCellの呼び出し中に、カスタムセル型オブジェクトによって例外がスローされた場合などです。コンポーネントの状態が変更される場合は常に、レイアウトの再計算がトリガされる可能性がありますが、再計算を伴わない変更もあります。並べ替えやフィルタリングなど、行や列を再配置するような変更では、必ずレイアウトの再計算が行われます。しかし、テキストだけを設定する場合は、FpSpreadクラスのAllowCellOverflowプロパティを有効にしている場合など、特定の条件下のみでレイアウトが再計算されます。レイアウトを一時停止しているにもかかわらず、一時停止前のレイアウト情報を使用してSPREADが問題なく描画を実行できる場合は、予期しない動作が行われる可能性があります。たとえば、スクロールを試みてもシートをスクロールできず、通知メッセージも表示されないという状況が起こりえます。
以下、レイアウトロジックの一時停止と再開以外の、パフォーマンスの向上方法です。
レイアウトを一時停止する場合の構成は次のようになります。
SuspendLayoutメソッド
任意のコードをここに挿入
ResumeLayoutメソッド
2つのメソッドの目的は、多数の変更を加える場合に、レイアウトへの変更を一時的に無視することで、変更のたびにレイアウトを再計算する冗長な中間処理が実行されないようにすることです。レイアウトの計算を一時停止している間、コントロールへの変更を追跡するイベントハンドラはレイアウトを再計算できず、描画コードは新たなレイアウトにアクセスできません。ネストしたループを使用して、すべてのセルに変更を加える場合は(全セルの値を変更する場合など)、事前にレイアウトを一時停止してから処理の完了後に再開することで、大きな効果を期待できます。
|
次のサンプルコードは、コントロールの描画を一時的に無効にし、セルに背景色を設定する例です。
C# |
コードのコピー
|
---|---|
fpSpread1.SuspendLayout();
fpSpread1.Sheets[0].Cells[0, 0, 499, 499].BackColor = Color.White;
fpSpread1.ResumeLayout(true);
|
Visual Basic |
コードのコピー
|
---|---|
FpSpread1.SuspendLayout()
FpSpread1.Sheets(0).Cells(0, 0, 499, 499).BackColor = Color.White
FpSpread1.ResumeLayout(True)
|