4

DataSource が DataTable である DataGridView があります。この DataTable にはブール列があり、DataGridView のチェックボックスとして解釈されます。

employeeSelectionTable.Columns.Add("IsSelected", typeof(bool));
...
employeeSelectionTable.RowChanged += selectionTableRowChanged;
dataGridViewSelectedEmployees.DataSource = employeeSelectionTable;

...

private void selectionTableRowChanged(object sender, DataRowChangeEventArgs e)
{
    if ((bool)e.Row["IsSelected"])
    {
        Console.Writeline("Is Selected");
    }
    else
    {
        Console.Writeline("Is Not Selected");
    }
    break;
}

ユーザーがチェックボックスを 1 回クリックすると、チェックボックスがオンになり、selectionTableRowChanged は「Is Selected」を出力します。

同様に、ユーザーが再度チェックすると、ボックスはクリアされ、selectionTableRowChanged は「選択されていません」を出力します。

ここに問題があります:

ユーザーがチェックボックスをダブルクリックすると、チェックボックスがチェックされ、RowChanged イベントが呼び出され (「Is Selected」)、チェックボックスがクリアされ、対応する RowChanged イベントは呼び出されません。現在、RowChanged イベントのサブスクライバーは同期していません。

私の現在の解決策は、DataGridView をサブクラス化し、WndProc をオーバーライドして WM_LBUTTONDBLLICK を食べることです。これにより、コントロールのダブルクリックは無視されます。より良い解決策はありますか?

4

7 に答える 7

2

空の DoubleClick イベント メソッドを作成しても役に立たない理由は、ダブルクリックが発生したときに発生する他の操作に加えて実行されるためです。

Windows で生成されたコードや、イベント ハンドラーをプログラムで追加する例を見ると、+= を使用してイベント ハンドラーを割り当てています。これは、既存のイベント ハンドラーに加えて、そのイベント ハンドラーを追加することを意味します。保存イベントで複数のイベント ハンドラーがトリガーされる可能性があります。

私の本能は、DataGridView クラスをオーバーライドしてから OnDoubleClick メソッドをオーバーライドし、ベースの OnDoubleClick メソッドを呼び出さないことでした。

しかし、私はこれをすぐにテストして、いくつかの興味深い結果を見ています.

次のテストクラスをまとめました。

using System;
using System.Windows.Forms;

namespace TestApp
{
    class DGV : DataGridView
    {
        private string test = "";

        protected override void OnDoubleClick(EventArgs e)
        {
            MessageBox.Show(test + "OnDoubleClick");
        }

        protected override void OnCellMouseDoubleClick(System.Windows.Forms.DataGridViewCellMouseEventArgs e)
        {
            MessageBox.Show(test + "OnCellMouseDoubleClick");
        }

        protected override void OnCellMouseClick(System.Windows.Forms.DataGridViewCellMouseEventArgs e)
        {
            if (e.Clicks == 1)
            {
                // Had to do this with a variable as using a MessageBox
                // here would block us from pulling off a double click
                test = "1 click ";
                base.OnCellMouseClick(e);
            }
            else
            {
                MessageBox.Show("OnCellMouseClick");
            }
        }
    }
}

次に、これをWindowsフォームに挿入し、チェックボックス列を追加してプログラムを実行しました。

新たに実行すると、チェックボックスをダブルクリックすると、メッセージボックスに「1 click OnDoubleClick」と表示されます。

これは、ダブルクリックの最初の部分で OnCellMouseClick が実行され、2 回目のクリックで OnDoubleClick が実行されることを意味します。

また、残念ながら、基本メソッドへの呼び出しを削除しても、チェックボックスがクリックを渡されるのを妨げているようには見えません。

このアプローチが機能するには、さらに進めて、ダブルクリックを無視する DataGridViewCheckBoxColumn と DataGridViewCheckBoxCell をオーバーライドする必要があると思われます。これが機能すると仮定すると、チェックボックスのダブルクリックを停止できますが、他の列コントロールでは引き続き許可されます。

カスタム DataGridView 列とセルの作成に関する別の質問への回答をここに投稿しまし

于 2008-09-29T21:52:51.920 に答える
2

DataGridView 内にチェックボックス列が必要な場合は、次のようなものを作成します。

DataGridViewCheckBoxCell checkBoxCell = new MyDataGridViewCheckBoxCell();
...
DataGridViewColumn col = new DataGridViewColumn(checkBoxCell);
...
col.Name = "colCheckBox";
...
this.dgItems.Columns.Add(col);

ここで、dgItems は DataGridView インスタンスです。

ご覧のとおり、DataGridViewCheckBoxCell クラスのサブクラスである MyDataGridViewCheckBoxCell クラスがあります。このサブクラスでは、次を定義します。

protected override void OnContentDoubleClick(DataGridViewCellEventArgs e)
{
    //This the trick to keep the checkbox in sync with other actions.
    //base.OnContentDoubleClick(e);
}

ユーザーがチェックボックス列のチェックボックスをダブルクリックすると、チェックボックスはシングルクリックのように動作します。これで同期の問題が解決するはずです。

于 2008-12-18T11:15:28.730 に答える
2

これは正確には洗練された解決策ではありませんが、単純に次のことを実行してみませんか?

private void dgv_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
    dgv_CellClick(sender, e);
}

これにより、2 番目の CellClick イベントが明示的に強制され、非同期が回避されます。

于 2009-09-01T17:19:36.463 に答える
1

DataGridView サブクラスの OnDoubleClick メソッドをオーバーライドして何もしないようにしましたが、それでもチェックボックスをもう一度変更することができました。

理想的には、DataTable の RowChanged イベントが 2 回呼び出されることを期待していました。オーバーライドされた OnDoubleClick メソッドを介して基になる DataTable に影響を与える方法はありますか?

于 2008-09-29T20:37:01.277 に答える
1

その低レベルを行う必要がある何らかの理由がありますか?DoubleClick メソッドは、それを食べる空のメソッドになることができますか?

于 2008-09-29T20:24:26.737 に答える
1

IsSelected 列を無制限のままにしないのはなぜですか? CellContentClick イベントを使用してデータを基になるデータテーブルにプッシュし、CellDoubleClick または RowChange イベントをそのままにしておきます。

private void dgv_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
  if(e.ColumnIndex == <columnIndex of IsSelected>)
  {
      string value = dgv[e.ColumnIndex, e.RowIndex].EditedFormattedValue;
       if( value == null || Convert.ToBoolean(value) == false)
          {
              //push false to employeeSelectionTable
          }
      else
          {
            //push true to employeeSelectionTable
          }

  }
}
于 2008-09-29T20:43:04.180 に答える
1

なぜ私がしなければならなかったのかわかりませんが、2 回目のクリック後に dgv を更新したばかりの datagridview 更新にアタッチされたタイマー ティック イベントを入れることができました。

セル内クリックイベント

**          _RefreshTimer = new Timer();
                _RefreshTimer.Tick += new EventHandler(RefreshTimer_Tick);
                _RefreshTimer.Interval = 100;
                _RefreshTimer.Start();

            }
        }

    }

    void RefreshTimer_Tick(object sender, EventArgs e)
    {
        dgv.Refresh();
        _RefreshTimer.Stop();
        _RefreshTimer = null;
    }**
于 2008-11-04T19:33:33.380 に答える