C#を使用してWindowsアプリケーションを開発しています。 DataGridView
を使用してデータを表示しています。その中にボタン列を追加しました。 DataGridViewのボタンでクリックイベントを処理する方法を知りたいです。
DataGridView
にボタンを追加し、クリックされたときにコードを実行したい。
簡単です-次の手順に従ってください。
まず、これが何をするかですNOT:
ここでの他の回答のいくつかの提案を避け、ボタンがクリックされたかどうかを判断するために列インデックスまたは列名をハードコーディングするための MSDNのドキュメント によって提供されます。クリックイベントはグリッド全体に登録されるため、何らかの理由でボタンがクリックされたことを確認する必要がありますが、ボタンが特定の列名またはインデックスにあると想定してそうするべきではありません...もっと簡単な方法があります...
また、どのイベントを処理するかに注意してください。繰り返しますが、ドキュメントと多くの例がこれを間違っています。ほとんどの例は、発生する CellClick
イベントを処理します。
セルのいずれかの部分がクリックされたとき。
...ただし、rowヘッダーがクリックされるたびに起動します。これには、単にe.RowIndex
値が0より小さいかどうかを判断するために、余分なコードを追加する必要があります
代わりに、発生するのは CellContentClick
のみです。
セル内のコンテンツがクリックされたとき
何らかの理由で、columnヘッダーもセル内の「コンテンツ」と見なされるため、以下でそれを確認する必要があります。
だからあなたがすべきことは次のとおりです:
まず、cast送信者をDataGridView
と入力して、設計時に内部プロパティを公開します。パラメーターの型を変更できますが、ハンドラーの追加または削除が難しい場合があります。
次に、ボタンがクリックされたかどうかを確認するには、イベントを発生させる列のタイプが DataGridViewButtonColumn
であることを確認します。送信者を既に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のタイプがDataGridViewExt
であることを確認してください。これはDataGridViewとまったく同じように機能するはずです。ただし、次のように処理できる追加のイベントも発生します。
Private Sub DataGridView1_ButtonClick(sender As DataGridView, e As DataGridViewCellEventArgs) _
Handles DataGridView1.CellButtonClick
'TODO - Button Clicked - Execute Code Here
End Sub
WinFormsについては、ここで完全に回答されています。 DataGridViewButtonColumn Class
そしてここ: 方法:GridViewコントロールのボタンイベントに応答する
実際に使用しているコントロールに応じて、Asp.Netの場合。 (あなたの質問はDataGridですが、Windowsアプリを開発しているので、使用するコントロールにはDataGridViewがあります...)
より良い答えは次のとおりです。
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のボタンクリックイベント
これは私の問題を解決します。
private void dataGridViewName_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
//Your code
}
ここの表に少し遅れていますが、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();
}
}
}
この美しさは、anyの名前の変更がコンパイラーによってキャッチされることに注意してください。テキスト名を変更してインデックスを作成するか、大文字を誤って使用すると、ランタイムの問題が発生します。ここでは、設計者が指定した名前に基づいて作成するオブジェクトの名前を実際に使用します。しかし、不一致はコンパイラによって注意を喚起されます。
クリックイベントを発生させ、値を別のフォームに渡すためのコードスニペットを次に示します。
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
に解析する必要はありません。
ほとんどの投票されたソリューションは間違っています。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");
}
}
たとえば、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);
}
よろしく:)
これを試すことができますが、列の順序についてはあまり気にしません。
private void TheGrid_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (TheGrid.Columns[e.ColumnIndex].HeaderText == "Edit")
{
// to do: edit actions here
MessageBox.Show("Edit");
}
}
誰かが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でイベントハンドラーを呼び出す基本 "
結構、噛みます。
あなたはこのような何かをする必要があります-明らかにそのすべてのメタコード。
button.Click += new ButtonClickyHandlerType(IClicked_My_Button_method)
iClicked_My_Button_methodメソッドをボタンのClickイベントまで「フック」します。これで、所有者クラス内からイベントが「起動」されるたびに、メソッドも起動されます。
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.
}
ここで実際の詳細はあなた次第ですが、他に何か不足していることがあれば概念的に私に知らせてください、私は助けようとします。
このようなボタン列を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);
リストの最後にToList()
メソッドを追加し、datagridview DataSourceにバインドします。
dataGridView1.DataSource = MyList.ToList();