6

現在開発中のアプリケーションでは、datagridviewを使用してデータを表示しています。それを埋めるには、ボタンを押す必要があります。バックグラウンドワーカーが実行を開始し、データテーブルを埋め、実行が終了すると、データグリッドのデータソースとしてデータテーブルを使用します。これは正常に機能し、UIは応答性を維持します。しかし今、私はそれらの値に応じて行に色付けを実装しました(私はまだそれで遊んでいるので、どんな提案も歓迎します):

        private void ApplyColoring()
    {
        if (dataGridView1.DataSource != null)
        {
            foreach (DataGridViewRow dataGridRow in dataGridView1.Rows)
            {
                // hardmap a color to a column
                IDictionary<Int32, Color> colorDictionary = new Dictionary<Int32, Color>();
                colorDictionary.Add( 7, Color.FromArgb(194, 235, 211));
                colorDictionary.Add( 8, Color.Salmon);
                colorDictionary.Add( 9, Color.LightBlue);
                colorDictionary.Add(10, Color.LightYellow);
                colorDictionary.Add(11, Color.LightGreen);
                colorDictionary.Add(12, Color.LightCoral);
                colorDictionary.Add(13, Color.Blue);
                colorDictionary.Add(14, Color.Yellow);
                colorDictionary.Add(15, Color.Green);
                colorDictionary.Add(16, Color.White);

                foreach (DataGridViewRow gridRow in dataGridView1.Rows)
                {
                    foreach (DataGridViewCell cell in gridRow.Cells)
                    {
                        if (colorDictionary.Keys.Contains(cell.ColumnIndex))
                        {
                            // standard background 
                            cell.Style.BackColor = Color.FromArgb(194, 235, 211);
                        }
                    }
                }

                IList<String> checkedValues = new List<String>();


                // first we loop through all the rows
                foreach (DataGridViewRow gridRow in dataGridView1.Rows)
                {
                    IDictionary<String, Int32> checkedVal = new Dictionary<String, Int32>();

                    // then we loop through all the data columns
                    int maxCol = dnsList.Count + 7;
                    for (int columnLoop = 7; columnLoop < maxCol; columnLoop++)
                    {
                        string current = gridRow.Cells[columnLoop].Value.ToString();

                        for (int checkLoop = 7; checkLoop < maxCol; checkLoop++)
                        {
                            string check = gridRow.Cells[checkLoop].Value.ToString();

                            if (!current.Equals(check))
                            {
                                if (checkedVal.Keys.Contains(current))
                                {
                                    gridRow.Cells[columnLoop].Style.BackColor = colorDictionary[checkedVal[current]];
                                }
                                else
                                {
                                    gridRow.Cells[columnLoop].Style.BackColor = colorDictionary[columnLoop];
                                    checkedVal.Add(current, columnLoop);
                                }
                            }
                        }
                    }
                }
            }
        }
    }

これは私に問題を与えています。着色が機能しないからではなく、機能します。しかし、それはそれを遅くするからです。初めては正常に動作しますが、もう一度ボタンを押すと、地獄のように遅くなり、データグリッドがちらつきます。これを後処理として実行したいので、backgroundworkerが完了した後に実行する必要があります(または実行する必要があります)。しかし、RunWorkerCompletedイベントからapplycoloringを呼び出すと、非常に遅くなります。これを防ぐにはどうすればよいですか?新しいクエリを実行している間(グリッド内の現在のデータを失わない間)にUIがちらつかないようにするにはどうすればよいですか?

4

6 に答える 6

19

ダブルバッファリングをオンにすることができます。

VB:

Imports System.Reflection

次の例をForm_Loadに入れます

Dim systemType As Type = DataGridView1.GetType()
Dim propertyInfo As PropertyInfo = systemType.GetProperty("DoubleBuffered", BindingFlags.Instance Or BindingFlags.NonPublic)
propertyInfo.SetValue(DataGridView1, True, Nothing)

C#の場合:次の手順に進みます:低速スクロールのDataGridViewの修正

乾杯

于 2011-07-22T13:04:39.217 に答える
6

2つの提案:

  1. ループの前にSuspendLayout()を呼び出し、ループの後にResumeLayout()を呼び出してみてください。他のほとんどのコントロールは、これをBeginUpdate()およびEndUpdate()(リストビュー、コンボボックスなど)と呼びます。
  2. 大量のデータを処理する場合は、DataGridViewでVirtualModeを使用してください。
于 2010-01-11T12:44:26.043 に答える
6

遅いデータグリッドに対してリフレクションダブルバッファリングを行う別の方法を見つけました。

データグリッドにダブルバッファリングを設定するために、リフレクションを使用して拡張メソッドを作成します。

public static class DataGridViewExtensioncs
{

    public static void DoubleBuffered(this DataGridView dgv, bool setting)
    {
        var dgvType = dgv.GetType();
        var pi = dgvType.GetProperty("DoubleBuffered",
              BindingFlags.Instance | BindingFlags.NonPublic);
        pi.SetValue(dgv, setting, null);
    }
}

次に、初期化子の形式で次のようにします。

this.dataGrid.DoubleBuffered(true);

これはEvolvedの回答と非常によく似ており、クレジットはShweta Lodhaに送られます:http: //www.codeproject.com/Tips/390496/Reducing-flicker-blinking-in-DataGridView

于 2014-08-11T10:07:49.670 に答える
2

ダブルバッファリングをオンにします

関数のコンパイルに必要な名前空間のリストは次のとおりです。

using System;
using System.Reflection;
using System.Windows.Forms;

public static class ExtensionMethods
{
   public static void DoubleBuffered(this DataGridView dgv, bool setting)
   {
      Type dgvType = dgv.GetType();
      PropertyInfo pi = dgvType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
      pi.SetValue(dgv, setting, null);
   }
}

次に、datagridviewを初期化します

dataGridView1.DoubleBuffered(true);
于 2017-06-26T00:30:31.347 に答える
1

更新する前にSuspendLayoutを呼び出してみてください。ResumeLayoutを呼び出すことを忘れないでください。

于 2010-01-11T12:46:07.587 に答える
1

グリッドをループしないことを強くお勧めします(ダブルバッファリングは役立つかもしれませんが、実際の問題を「隠す」だけです)。これは多くのレンダリングを生成するためです。

このような目的のために、私はイベントハンドラーを使用します。

dataGridView1.CellValueChanged += new DataGridViewCellEventHandler(dataGridView1_CellValueChanged);

private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
    {
            if (dataGridView1.Columns[5].Index == e.ColumnIndex && e.RowIndex >= 0 && dataGridView1[5, e.RowIndex].Value.ToString() != "0")
            {
                e.CellStyle.BackColor = Color.PaleGreen;
            }
    }

セルの値が変更されると、グリッドは自動的に更新され、背景色が変更されます

于 2016-08-05T09:08:19.587 に答える