2012-03-04 24 views
2

DataGridViewをフォームに実装し、VirtualModeを正常に実装しました。これにより、ローカルキャッシュからセルデータが取得され、グリッド/ページングなどをポピュレートするときに、すべてが正常に動作しているように見えます。DataGridView.CellValueNeededイベントを処理してセルを設定します。AutoResizeColumnを呼び出すタイミングは、VirtualModeのWinforms DataGridViewですか?

DataGridViewでは、AutoSizeColumnsModeプロパティがDataGridViewAutoSizeColumnsMode.DisplayedCellsに設定されています。私は、VirtualModeを使用すると、DataGridViewはセルを設定した後にAutoSizeColumnsModeを尊重するようには見えないことに気付きました。私はthis articleを調べましたが、解決策が見つかりませんでした。私は最終的にやりたい何

AutoSizeColumnsMode性質に依存しているのではなく、サイズを変更するためにどこか.AutoResizeColumn()方法を呼び出すので、私が最初に列を自動サイズ調整が、その後、ユーザがサイズを変更することができないことです。

私は、限定された、あるいはまったく成功して次のことを試してみました:

  1. セットDataGridView.AutoSizeColumnsMode.Noneに。それは 繰り返し.CellValueNeededを上げるため、そして、私の .CellValueNeededハンドラ

    private void dataGridView_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e) 
    { 
        // ... Get cell value from cache 
        dataGridView.AutoResizeColumn(e.ColumnIndex, DataGridViewAutoSizeColumnMode.DisplayedCells); 
    } 
    

    にこれはおそらくStackOverFlowExceptionをスローします。

  2. .CellFormatting イベントハンドラを除き、まったく同じことをしようとしました。同じStackOverFlowExceptionを得ました。

  3. DataGridView.SuspendLayout/ResumeLayoutでとせずにしようとしました:

    private void dataGridView_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e) 
    { 
        // ... Get cell value from cache 
        dataGridView.CellValueNeeded -= dataGridView_CellValueNeeded; 
        dataGridView.AutoResizeColumn(e.ColumnIndex, DataGridViewAutoSizeColumnMode.DisplayedCells); 
        dataGridView.CellValueNeeded += dataGridView_CellValueNeeded; 
    } 
    

    これは、すべての空白セル、ありませんので使用を提供します。

  4. この1つは実際には多少私は理解していない理由のために、働く:

    private void dataGridView_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e) 
    { 
        // ... Get cell value from cache 
        dataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.DisplayedCells; 
    } 
    

    それは正しく、列のサイズを変更し、繰り返し必要なすべてのセルの値でそれを呼び出すために持っている奇妙に思えます。また、直後に[いいえ]を設定することはできません。またはStackOverFlowExceptionにもう一度入力してください。したがって、ユーザーが列のサイズを変更できるようにすることはできません。

  5. .UpdateCellValue()を私の.CellValueNeededハンドラースローStackOverFlowExceptionの記事で説明したように呼び出します。

だから、それがオーバーフローするまで、それは.CellValueNeededは発生しません.AutoResizeColumn()どこかで呼び出すことが可能ですか? #4はオートサイズ機能を実行する能力を持っているように思われるので、手動でどこからでも呼び出すことができるようです。

答えて

2

私はまだ他の人の言葉に耳を傾けることに興味がありますが、これが解決策になると思います。

DataGridViewによって発生した他のイベントのいくつかを見て、.RowPostPaintというイベントが見つかりました。これは、初期データロード時に列の自動サイズ変更を達成

private void dataGridView_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e) 
{ 
    if (dataGridView.AllowUserToResizeColumns) //So not to run unnecessarily 
    { 
     return; 
    } 
    var lastIndex = dataGridView.Rows.GetLastRow(DataGridViewElementStates.Displayed); 
    if (e.RowIndex == lastIndex) //Only do on the last displayed row 
    { 
     dataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells); 
     dataGridView.AllowUserToResizeColumns = true; // User has control from here on 
    } 
} 

、そこからユーザーが再サイズすることができます:私は、次のハンドラを作成しました。これは一度だけ実行されるので、必要なすべてのセル値よりも優れています。最初のデータを読み込む前にdataGridView.AllowUserToResizeColumns = falseに設定する必要があります。

これは請求書に合うようです。ユーザーは最初の読み込み時に列がきれいに表示され、そこから調整することができます。ほとんどのデータは行ごとに匹敵する長さなので、ほとんどの場合、それを切り捨てるかスペースを無駄にしないでください。

0

他者の言うことに興味があると述べているので、私は、仮想データグリッドでの自動列リサイズの使い方について少し違ったアプローチを取り入れました。

初期のAutoResizeColumns呼び出しは、フォームと子コンポーネントが初期化されて表示されるように、表示イベントの後に配置されます。また、RowPostPaintではなく、DataGridView Scrollイベントを配線することで、このイベントが発生する頻度が少なくてすみますので、効率的です。

using System.Collections.Generic; 
using System.Windows.Forms; 

namespace DataGridViewTest 
{ 
    public partial class DataGridViewForm : Form 
    { 
     private List<string> dataSource; 

     public DataGridViewForm() 
     { 
      InitializeComponent(); 

      // Enable VirtualMode for dataGridView1 
      dataGridView1.VirtualMode = true; 

      // Wire CellValueNeeded event handler 
      dataGridView1.CellValueNeeded += DataGridView1_CellValueNeeded; 

      // Wire Scroll event handler 
      dataGridView1.Scroll += DataGridView1_Scroll; 

      // Wire form Shown event handler 
      this.Shown += DataGridViewForm_Shown; 
     } 

     private void DataGridViewForm_Shown(object sender, System.EventArgs e) 
     { 
      // Populate dataGridView1 here to avoid perception of a long form startup time 
      populateDataGridView(); 

      // Resize columns after the form is initialized and displayed on screen, 
      // otherwise calling this method won't actually have an effect on column sizes 
      dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells); 
     } 

     private void DataGridView1_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e) 
     { 
      // Set the triggering cell's value to the corresponding value from dataSource 
      e.Value = dataSource[e.RowIndex]; 
     } 

     private void DataGridView1_Scroll(object sender, ScrollEventArgs e) 
     { 
      // Resize columns again, but only if a vertical scroll just happened 
      if (e.ScrollOrientation == ScrollOrientation.VerticalScroll) 
      { 
       dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells); 
      } 
     } 

     private void populateDataGridView() 
     { 
      fetchIntoDataSource(); 

      associateDataSourceToDataGridView(); 
     } 

     private void fetchIntoDataSource() 
     { 
      dataSource = new List<string>(); 

      // Insert a test string into dataSource many times 
      for (int i = 0; i < 1000; i++) 
      { 
       dataSource.Add("test string"); 
      } 
     } 

     private void associateDataSourceToDataGridView() 
     { 
      // Synchronize dataGridView1.RowCount to dataSource.Count 
      // This is necessary for the CellValueNeeded event to fire 
      dataGridView1.RowCount = dataSource.Count; 
     } 
    } 
} 
関連する問題