[解決済み] Datagridviewのボタン列のクリックイベントを処理するには?
質問
C#を使用してWindowsアプリケーションを開発しています。私は、以下のものを使用しています。
DataGridView
を使用してデータを表示します。その中にボタン列を追加しました。そのボタンのクリックイベントを
DataGridView
.
解決方法は?
にボタンを追加しました。
DataGridView
クリックされたときに何らかのコードを実行させたい。
簡単です。以下のステップを踏むだけです。
注意事項
まず、以下の通りです。 NOT を行うことです。
私は、ここでの他のいくつかの回答での提案や、さらに、その回答が提供した のドキュメントを参照してください。 ボタンがクリックされたかどうかを判断するために、列インデックスまたは列名をハードコードする必要があります。 クリックイベントはグリッド全体に対して登録されるので、何らかの方法でボタンがクリックされたことを判断する必要がありますが、ボタンが特定の列名やインデックスに存在すると仮定してそれを行うべきではありません...より簡単な方法があります...。
また、どのイベントを処理するかは注意が必要です。 これもまた、ドキュメントや多くの例で間違っています。 ほとんどの例では
CellClick
イベントが発生します。
セルのどこかがクリックされたとき。
...しかし
行
ヘッダーがクリックされました。 このため、単に
e.RowIndex
が0より小さい場合
代わりに
CellContentClick
だけが発生します。
セル内のコンテンツがクリックされたとき
何らかの理由で 列 ヘッダもセル内の「コンテンツ」とみなされるので、以下でもそのチェックをする必要があります。
ドス
では、どうすればいいのか、ご紹介しましょう。
まず
キャスト
と入力すると、送信者は
DataGridView
を使用すると、設計時に内部プロパティを公開することができます。 パラメータで型を変更することもできますが、その場合、ハンドラの追加や削除が面倒になる場合があります。
次に、ボタンがクリックされたかどうかを確認するには、イベントを発生させた列の型が
DataGridViewButtonColumn
. なぜなら、すでに送信者をキャストして
DataGridView
を取得することができます。
Columns
コレクションを作成し、現在のカラムを選択するには
e.ColumnIndex
. 次に、そのオブジェクトが
DataGridViewButtonColumn
.
もちろん、グリッドごとに複数のボタンを区別する必要がある場合は、カラム名やインデックスに基づいて選択することができますが、それは最初のチェックではありません。 ボタンがクリックされたことをまず確認してから、それ以外のことを適切に処理するようにしましょう。 1つのグリッドにボタンが1つしかない場合、ほとんどの場合、すぐにレースに参加することができます。
すべてをまとめる
C#
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
var senderGrid = (DataGridView)sender;
if (senderGrid.Columns[e.ColumnIndex] is DataGridViewButtonColumn &&
e.RowIndex >= 0)
{
//TODO - Button Clicked - Execute Code Here
}
}
VB
Private Sub DataGridView1_CellContentClick(sender As System.Object, e As DataGridViewCellEventArgs) _
Handles DataGridView1.CellContentClick
Dim senderGrid = DirectCast(sender, DataGridView)
If TypeOf senderGrid.Columns(e.ColumnIndex) Is DataGridViewButtonColumn AndAlso
e.RowIndex >= 0 Then
'TODO - Button Clicked - Execute Code Here
End If
End Sub
アップデート1 - カスタムイベント
もし、少し楽しみたいのであれば、DataGrid上でボタンがクリックされるたびに発生する独自のイベントを追加することができます。 データグリッドそのものにイベントを追加することはできませんが、フォームにカスタムイベントを追加し、適切なタイミングでイベントを発生させることができます。 少しコードが多くなりますが、ボタンがクリックされたときに何をしたいかと、ボタンがクリックされたかどうかを判断する方法を分離することができるという利点があります。
イベントを宣言し、適切なタイミングでイベントを発生させ、それを処理するだけです。 こんな感じになります。
Event DataGridView1ButtonClick(sender As DataGridView, e As DataGridViewCellEventArgs)
Private Sub DataGridView1_CellContentClick(sender As System.Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick
Dim senderGrid = DirectCast(sender, DataGridView)
If TypeOf senderGrid.Columns(e.ColumnIndex) Is DataGridViewButtonColumn AndAlso e.RowIndex >= 0 Then
RaiseEvent DataGridView1ButtonClick(senderGrid, e)
End If
End Sub
Private Sub DataGridView1_ButtonClick(sender As DataGridView, e As DataGridViewCellEventArgs) Handles Me.DataGridView1ButtonClick
'TODO - Button Clicked - Execute Code Here
End Sub
アップデート2 - グリッドの拡張
もし、このようなことをやってくれるグリッドがあれば最高です。 最初の質問に簡単に答えることができます。
you've added a button to your DataGridView and you want to run some code when it's clicked
. を拡張したアプローチを紹介します。
DataGridView
. すべてのライブラリでカスタムコントロールを提供しなければならないという手間に見合うものではないかもしれませんが、少なくとも、ボタンがクリックされたかどうかを判断するために使用するコードを最大限に再利用することができます。
これをアセンブリに追加するだけです。
Public Class DataGridViewExt : Inherits DataGridView
Event CellButtonClick(sender As DataGridView, e As DataGridViewCellEventArgs)
Private Sub CellContentClicked(sender As System.Object, e As DataGridViewCellEventArgs) Handles Me.CellContentClick
If TypeOf Me.Columns(e.ColumnIndex) Is DataGridViewButtonColumn AndAlso e.RowIndex >= 0 Then
RaiseEvent CellButtonClick(Me, e)
End If
End Sub
End Class
これで終わりです。 もう二度と触らないようにしましょう。 データグリッドの型が
DataGridViewExt
は、DataGridViewと全く同じように動作するはずです。 ただし、追加イベントも発生するので、このように処理することができます。
Private Sub DataGridView1_ButtonClick(sender As DataGridView, e As DataGridViewCellEventArgs) _
Handles DataGridView1.CellButtonClick
'TODO - Button Clicked - Execute Code Here
End Sub
関連
-
[解決済み】コレクションが変更され、列挙操作が実行されないことがある。
-
[解決済み】「The breakpoint will not currently be hit」を改善するには?このドキュメントにはシンボルが読み込まれていません。" という警告はどうすれば改善されますか?
-
[解決済み】パディングが無効で、削除できない?
-
[解決済み】クロススレッド操作が有効でない。作成されたスレッド以外のスレッドからアクセスされたコントロール
-
[解決済み】ユーザー設定値を別のユーザー設定値で設定する
-
[解決済み] なぜList<T>を継承しないのですか?
-
[解決済み] HTTP POST Web リクエストの作成方法
-
[解決済み] DateTimeとDateTimeOffsetの比較
-
[解決済み] 数字しか入力できないテキストボックスの作り方を教えてください。
-
[解決済み] Microsoft.ACE.OLEDB.12.0' プロバイダがローカルマシンに登録されていません。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】指定されたキャストが有効でない?
-
[解決済み】コンパイルエラー「未割り当てのローカル変数を使用しています」が発生したのはなぜですか?
-
解決済み] Critical error detected c0000374 - C++ dll returns pointer off allocated memory to C# [解決済み] Critical error detected c0000374 - C++ dll returns pointer off allocated memory to C#.
-
[解決済み】リソースの読み込みに失敗した:ステータス500(内部サーバーエラー)のサーバーの応答)
-
[解決済み】取り消せないメンバはメソッドのように使えない?
-
[解決済み】HRESULTからの例外:0x800A03ECエラー
-
[解決済み] ...基礎となる接続は閉じられました。予期しないエラーが受信で発生しました
-
[解決済み】インデックスが範囲外でした。コレクションパラメータname:indexのサイズより小さく、非負でなければなりません。
-
[解決済み】Microsoft.Extensions.LoggingからILoggerを解決することができない
-
[解決済み】名前 'ViewBag' が現在のコンテキストに存在しない - Visual Studio 2015