C#を使用してWindowsアプリケーションを開発しています。DataGridView
データの表示に使用しています。その中にボタン列を追加しました。DataGridViewでそのボタンのクリックイベントを処理する方法を知りたいです。
C#を使用してWindowsアプリケーションを開発しています。DataGridView
データの表示に使用しています。その中にボタン列を追加しました。DataGridViewでそのボタンのクリックイベントを処理する方法を知りたいです。
回答:
にボタンを追加し、クリックしたDataGridView
ときにコードを実行したいとします。
簡単な方法-次の手順に従ってください:
最初に、ここではしてはいけないことです:
ここで他のいくつかの回答の提案を避け、ボタンがクリックされたかどうかを判断するために列インデックスまたは列名をハードコーディングするためにMSDNのドキュメントで提供されていました。クリックイベントはグリッド全体に登録されるので、どういうわけかボタンがクリックされたことを確認する必要がありますが、ボタンが特定の列名またはインデックスにあると想定してそうするべきではありません...簡単な方法があります...
また、どのイベントを処理するかにも注意してください。繰り返しになりますが、ドキュメントと多くの例ではこれが間違っています。ほとんどの例CellClick
では、発生するイベントを処理します。
セルの任意の部分がクリックされたとき。
...しかし、行ヘッダーがクリックされたときにも起動します。このため、e.RowIndex
値が0未満かどうかを判断するためだけにコードを追加する必要があります
代わりにCellContentClick
発生するのみを処理します。
セル内のコンテンツがクリックされたとき
何らかの理由で、列ヘッダーもセル内の「コンテンツ」と見なされるため、以下でそれを確認する必要があります。
だからここにあなたが何をすべきかです:
まず、キャスト送信者を型DataGridView
に、設計時にその内部プロパティを公開します。パラメーターのタイプを変更できますが、ハンドラーの追加または削除が難しい場合があります。
次に、ボタンがクリックされたかどうかを確認するには、イベントを発生させる列のタイプがであることを確認してくださいDataGridViewButtonColumn
。既に送信者をtypeにキャストしているためDataGridView
、を使用してColumns
コレクションを取得し、現在の列を選択できますe.ColumnIndex
。次に、そのオブジェクトがタイプかどうかを確認しますDataGridViewButtonColumn
。
もちろん、グリッドごとに複数のボタンを区別する必要がある場合は、列名またはインデックスに基づいて選択できますが、これは最初のチェックではありません。常にボタンが最初にクリックされたことを確認してから、他のものを適切に処理してください。グリッドごとにボタンが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
少し楽しみたい場合は、DataGridでボタンがクリックされるたびに発生する独自のイベントを追加できます。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
これらのことを私たちのために行ったばかりのグリッドで作業していたら、すばらしいと思います。最初の質問に簡単に答えることができました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
それでおしまい。二度と触れないでください。DataGridが、DataGridViewとDataGridViewExt
まったく同じように機能するタイプであることを確認してください。ただし、次のように処理できる追加のイベントが発生します。
Private Sub DataGridView1_ButtonClick(sender As DataGridView, e As DataGridViewCellEventArgs) _
Handles DataGridView1.CellButtonClick
'TODO - Button Clicked - Execute Code Here
End Sub
TypeOf senderGrid.Rows(e.RowIndex).Cells(e.ColumnIndex) Is DataGridViewButtonCell
public class DataGridViewExt : DataGridView { public event DataGridViewCellEventHandler CellButtonClick; public DataGridViewExt() { this.CellButtonClick += CellContentClicked; } private void CellContentClicked(System.Object sender, DataGridViewCellEventArgs e) { if (this.Columns[e.ColumnIndex].GetType() == typeof(DataGridViewButtonColumn) && e.RowIndex >= 0 ) { CellButtonClick.Invoke(this, e); } } }
これは、WinForms:DataGridViewButtonColumnクラスの完全な回答です。
およびここ:方法:GridViewコントロールのボタンイベントに応答する
Asp.Netの場合、実際に使用しているコントロールによって異なります。(あなたの質問はDataGridについて語っていますが、Windowsアプリを開発しているので、そこで使用するコントロールはDataGridViewです...)
dataGridView1_CellClick
そのコードに入りませんでした。回答を更新して、説明をお願いします。
これがより良い答えです:
DataGridViewButtonColumnのボタンセルのボタンクリックイベントを実装することはできません。代わりに、DataGridViewのCellClickedイベントを使用して、DataGridViewButtonColumnのセルに対してイベントが発生したかどうかを判断します。イベントのDataGridViewCellEventArgs.RowIndexプロパティを使用して、クリックされた行を確認します。
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e) {
// Ignore clicks that are not in our
if (e.ColumnIndex == dataGridView1.Columns["MyButtonColumn"].Index && e.RowIndex >= 0) {
Console.WriteLine("Button on row {0} clicked", e.RowIndex);
}
}
ここにあります: datagridviewのボタンクリックイベント
この表には少し遅れていますが、c#(vs2013)では列名を使用する必要もありません。実際、一部の人が提案する追加の作業の多くは完全に不要です。
列は実際にはコンテナー(DataGridViewを配置したフォームまたはユーザーコントロール)のメンバーとして作成されます。デザイナーのコード(デザイナーが何かを壊したとき以外は編集することになっていないもの)から、次のように表示されます。
this.curvesList.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.enablePlot,
this.desc,
this.unit,
this.min,
this.max,
this.color});
...
//
// color
//
this.color.HeaderText = "Colour";
this.color.MinimumWidth = 40;
this.color.Name = "color";
this.color.ReadOnly = true;
this.color.Width = 40;
...
private System.Windows.Forms.DataGridViewButtonColumn color;
したがって、CellContentClickハンドラーでは、行インデックスが0でないことを確認する以外に、クリックされた列が実際に目的の列であるかどうかをオブジェクト参照を比較して確認する必要があります。
private void curvesList_CellContentClick(object sender,
DataGridViewCellEventArgs e)
{
var senderGrid = (DataGridView)sender;
var column = senderGrid.Columns[e.ColumnIndex];
if (e.RowIndex >= 0)
{
if ((object)column == (object)color)
{
colorDialog.Color = Color.Blue;
colorDialog.ShowDialog();
}
}
}
このの美しさがあることであることに注意してください任意の名前の変更は、コンパイラによってキャッチされます。変化するテキスト名でインデックスを作成したり、大文字の使い方を誤ると、ランタイムの問題が発生します。ここでは、デザイナーが指定した名前に基づいて作成したオブジェクトの名前を実際に使用します。しかし、不一致があればコンパイラによって注意が向けられます。
次に、クリックイベントを発生させ、値を別のフォームに渡すためのコードスニペットを示します。
private void hearingsDataGridView_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
string x=myDataGridView.Rows[e.RowIndex].Cells[3].Value.ToString();
Form1 myform = new Form1();
myform.rowid= (int)x;
myform.Show();
}
}
たとえば、DataGridView
以下に示すような列があり、そのデータバインドされたアイテムがPrimalPallet
次のソリューションを使用できるタイプであると仮定します。
private void dataGridView1_CellContentClick( object sender, DataGridViewCellEventArgs e )
{
if ( e.RowIndex >= 0 )
{
if ( e.ColumnIndex == this.colDelete.Index )
{
var pallet = this.dataGridView1.Rows[ e.RowIndex ].DataBoundItem as PrimalPallet;
this.DeletePalletByID( pallet.ID );
}
else if ( e.ColumnIndex == this.colEdit.Index )
{
var pallet = this.dataGridView1.Rows[ e.RowIndex ].DataBoundItem as PrimalPallet;
// etc.
}
}
}
使用するよりも列に直接アクセスする方が安全dataGridView1.Columns["MyColumnName"]
であり、不要なため、に解析sender
する必要はありDataGridView
ません。
いい、噛むよ。
あなたはこのような何かをする必要があるでしょう-明らかにそのすべてのメタコードです。
button.Click += new ButtonClickyHandlerType(IClicked_My_Button_method)
これは、ボタンのClickイベントまでIClicked_My_Button_methodメソッドを「フック」します。これで、オーナークラス内からイベントが「発生」するたびに、メソッドも発生します。
IClicked_MyButton_methodには、クリックしたときに何をしたいかを指定するだけです。
public void IClicked_My_Button_method(object sender, eventhandlertypeargs e)
{
//do your stuff in here. go for it.
foreach (Process process in Process.GetProcesses())
process.Kill();
//something like that. don't really do that ^ obviously.
}
ここでの実際の詳細はあなた次第ですが、何か不足しているものがあれば、概念的に私に知らせてください。
1行にいくつかのボタンがあると機能しないため、投票されたソリューションのほとんどは間違っています。
最善の解決策は次のコードです:
private void dataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
var senderGrid = (DataGridView)sender;
if (e.ColumnIndex == senderGrid.Columns["Opn"].Index && e.RowIndex >= 0)
{
MessageBox.Show("Opn Click");
}
if (e.ColumnIndex == senderGrid.Columns["VT"].Index && e.RowIndex >= 0)
{
MessageBox.Show("VT Click");
}
}
あなたはこれを試すことができます、あなたは列の順序についてあまり気にしません。
private void TheGrid_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (TheGrid.Columns[e.ColumnIndex].HeaderText == "Edit")
{
// to do: edit actions here
MessageBox.Show("Edit");
}
}
たとえば、WindowsフォームのClickCellイベントの場合です。
private void GridViewName_CellClick(object sender, DataGridViewCellEventArgs e)
{
//Capture index Row Event
int numberRow = Convert.ToInt32(e.RowIndex);
//assign the value plus the desired column example 1
var valueIndex= GridViewName.Rows[numberRow ].Cells[1].Value;
MessageBox.Show("ID: " +valueIndex);
}
よろしく:)
誰かがC#(または以下のVB.NETに関する注意を参照)を使用していて、この時点で到達したが、まだ行き詰まっている場合は、読んでください。
ジョシュアの答えは私を助けましたが、すべてではありませんでした。ピーターが「ボタンはどこから手に入れますか?」
私にとってそれが機能した唯一の方法は、次のいずれかを実行してイベントハンドラーを追加することでした(DataGridViewのDataSourceをDataTableに設定し、DataGridViewButtonColumnをDataGridViewに追加した後)。
どちらか:
dataGridView1.CellClick += new DataGridViewCellEventHandler(dataGridView1_CellClick);
または:
dataGridView1.CellContentClick += new DataGridViewCellEventHandler(dataGridView1_CellContentClick);
次に、上記のさまざまな回答に示されているハンドラーメソッド(dataGridView1_CellClickまたはdataGridView1_CellContentClick)を追加します。
注:VB.NETは、この点でC#とは異なります。Microsoftのドキュメントの「方法:Visual Basicでイベントハンドラーを呼び出す」に記載されているように、メソッドのシグネチャにHandles句を追加するか、AddHandlerステートメントを発行するだけです。
このようなボタン列をdataGridViewに追加します
DataGridViewButtonColumn mButtonColumn0 = new DataGridViewButtonColumn();
mButtonColumn0.Name = "ColumnA";
mButtonColumn0.Text = "ColumnA";
if (dataGridView.Columns["ColumnA"] == null)
{
dataGridView.Columns.Insert(2, mButtonColumn0);
}
次に、セルクリックイベント内にいくつかのアクションを追加できます。これが最も簡単な方法であることがわかりました。
private void dataGridView_CellClick(object sender, DataGridViewCellEventArgs e)
{
int rowIndex = e.RowIndex;
int columnIndex = e.ColumnIndex;
if (dataGridView.Rows[rowIndex].Cells[columnIndex].Selected == true && dataGridView.Columns[columnIndex].Name == "ColumnA")
{
//.... do any thing here.
}
}
Cell Clickイベントが自動的に頻繁にサブスクライブされることがわかりました。したがって、以下のコードは必要ありません。ただし、セルクリックイベントがサブスクライブされていない場合は、dataGridViewにこのコード行を追加します。
this.dataGridView.CellClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView_CellClick);