Tôi đang phát triển một ứng dụng windows bằng C #. Tôi đang sử dụng DataGridView
để hiển thị dữ liệu. Tôi đã thêm một cột nút trong đó. Tôi muốn biết làm thế nào tôi có thể xử lý sự kiện nhấp vào nút đó trong DataGridView.
Tôi đang phát triển một ứng dụng windows bằng C #. Tôi đang sử dụng DataGridView
để hiển thị dữ liệu. Tôi đã thêm một cột nút trong đó. Tôi muốn biết làm thế nào tôi có thể xử lý sự kiện nhấp vào nút đó trong DataGridView.
Câu trả lời:
Bạn đã thêm một nút cho bạn DataGridView
và bạn muốn chạy một số mã khi nhấp vào.
Dễ dàng dễ dàng - chỉ cần làm theo các bước sau:
Đầu tiên, đây là những gì KHÔNG nên làm:
Tôi sẽ tránh các đề xuất trong một số câu trả lời khác ở đây và thậm chí được cung cấp bởi tài liệu tại MSDN để mã hóa chỉ mục cột hoặc tên cột để xác định xem có nhấp vào nút không. Sự kiện nhấp đăng ký cho toàn bộ lưới, vì vậy bằng cách nào đó bạn cần xác định rằng một nút đã được nhấp, nhưng bạn không nên làm như vậy bằng cách giả sử rằng nút của bạn nằm trong một tên hoặc chỉ mục cột cụ thể ... có một cách dễ dàng hơn ...
Ngoài ra, hãy cẩn thận những sự kiện bạn muốn xử lý. Một lần nữa, các tài liệu và nhiều ví dụ nhận được điều này sai. Hầu hết các ví dụ xử lý CellClick
sự kiện sẽ kích hoạt:
khi bất kỳ phần nào của một ô được bấm.
... nhưng cũng sẽ kích hoạt bất cứ khi nào tiêu đề hàng được nhấp. Điều này đòi hỏi phải thêm mã bổ sung đơn giản để xác định xem e.RowIndex
giá trị nhỏ hơn 0
Thay vào đó xử lý những CellContentClick
gì chỉ xảy ra:
khi nội dung trong một ô được bấm
Vì bất kỳ lý do gì, tiêu đề cột cũng được coi là "nội dung" trong một ô, vì vậy chúng tôi vẫn phải kiểm tra phần bên dưới.
Vì vậy, đây là những gì bạn nên làm:
Đầu tiên, bỏ người gửi để nhập DataGridView
để hiển thị các thuộc tính bên trong của nó tại thời điểm thiết kế. Bạn có thể sửa đổi loại trên tham số, nhưng điều đó đôi khi có thể khiến việc thêm hoặc xóa trình xử lý trở nên khó khăn.
Tiếp theo, để xem nếu một nút được nhấp, chỉ cần kiểm tra để đảm bảo rằng cột nâng sự kiện là loại DataGridViewButtonColumn
. Vì chúng tôi đã chọn người gửi để nhập DataGridView
, chúng tôi có thể lấy Columns
bộ sưu tập và chọn cột hiện tại bằng cách sử dụng e.ColumnIndex
. Sau đó kiểm tra xem đối tượng đó có thuộc loại không DataGridViewButtonColumn
.
Tất nhiên, nếu bạn cần phân biệt giữa nhiều nút trên mỗi lưới, thì bạn có thể chọn dựa trên tên hoặc chỉ mục của cột, nhưng đó không phải là kiểm tra đầu tiên của bạn. Luôn đảm bảo rằng một nút được nhấp trước và sau đó xử lý mọi thứ khác một cách thích hợp. Trong hầu hết các trường hợp bạn chỉ có một nút duy nhất cho mỗi lưới, bạn có thể nhảy ngay vào các cuộc đua.
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
Nếu bạn muốn có một chút niềm vui, bạn có thể thêm sự kiện của riêng mình để được nâng lên bất cứ khi nào một nút được nhấp vào DataGrid. Bạn không thể thêm nó vào DataGrid, mà không bị lộn xộn với tính kế thừa, v.v., nhưng bạn có thể thêm một sự kiện tùy chỉnh vào biểu mẫu của mình và kích hoạt nó khi thích hợp. Đó là một mã nhiều hơn một chút, nhưng nhược điểm là bạn đã tách ra những gì bạn muốn làm khi một nút được nhấp với cách xác định nếu một nút được nhấp.
Chỉ cần tuyên bố một sự kiện, nâng cao nó khi thích hợp và xử lý nó. Nó sẽ trông giống thế này:
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
Điều tuyệt vời là nếu chúng ta làm việc với một mạng lưới vừa làm những điều này cho chúng ta. Chúng tôi có thể trả lời câu hỏi ban đầu một cách dễ dàng : you've added a button to your DataGridView and you want to run some code when it's clicked
. Đây là một cách tiếp cận mở rộng DataGridView
. Nó có thể không có giá trị rắc rối khi phải cung cấp một điều khiển tùy chỉnh với mọi thư viện, nhưng ít nhất nó sử dụng tối đa mã được sử dụng để xác định nếu một nút được nhấp.
Chỉ cần thêm nó vào hội đồng của bạn:
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
Đó là nó. Không bao giờ chạm vào nó một lần nữa. Đảm bảo DataGrid của bạn thuộc loại DataGridViewExt
sẽ hoạt động chính xác như DataGridView. Ngoại trừ nó cũng sẽ đưa ra một sự kiện bổ sung mà bạn có thể xử lý như thế này:
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); } } }
Điều đó đã được trả lời đầy đủ ở đây cho WinForms: Lớp DataGridViewButtonColumn
và tại đây: Cách: Trả lời các Sự kiện Nút trong Điều khiển GridView
cho Asp.Net tùy thuộc vào điều khiển bạn thực sự sử dụng. (Câu hỏi của bạn nói DataGrid, nhưng bạn đang phát triển ứng dụng Windows, do đó, kiểm soát bạn đang sử dụng có DataGridView ...)
dataGridView1_CellClick
trong mã đó. Bạn có thể cập nhật câu trả lời của bạn và cho tôi một số mô tả.
Đây là câu trả lời tốt hơn:
Bạn không thể triển khai một sự kiện được nhấp vào nút cho các ô của nút trong DataGridViewButtonColumn. Thay vào đó, bạn sử dụng sự kiện CellClicky của DataGridView và xác định xem sự kiện đó có được kích hoạt cho một ô trong DataGridViewButtonColumn của bạn không. Sử dụng thuộc tính DataGridViewCellEventArss.RowIndex của sự kiện để tìm ra hàng nào được nhấp.
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);
}
}
tìm thấy ở đây: nút bấm sự kiện trong datagridview
Một chút muộn để bàn ở đây, nhưng trong c # (vs2013), bạn không cần phải sử dụng tên cột, trong thực tế, rất nhiều công việc phụ mà một số người đề xuất là hoàn toàn không cần thiết.
Cột thực sự được tạo như một thành viên của bộ chứa (biểu mẫu hoặc điều khiển người dùng mà bạn đã đặt DataGridView vào). Từ mã nhà thiết kế (những thứ bạn không cần phải chỉnh sửa trừ khi nhà thiết kế phá vỡ thứ gì đó), bạn sẽ thấy một cái gì đó như:
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;
Vì vậy, trong trình xử lý CellContentClick, ngoài việc đảm bảo chỉ số hàng không bằng 0, bạn chỉ cần kiểm tra xem cột được nhấp có thực sự là cột bạn muốn hay không bằng cách so sánh các tham chiếu đối tượng:
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();
}
}
}
Lưu ý rằng cái hay của việc này là bất kỳ thay đổi tên nào cũng sẽ bị trình biên dịch bắt gặp. Nếu bạn lập chỉ mục với một tên văn bản thay đổi hoặc viết hoa không chính xác, bạn bị ràng buộc cho các vấn đề thời gian chạy. Ở đây bạn thực sự sử dụng tên của một đối tượng, mà nhà thiết kế tạo ra dựa trên tên bạn đã cung cấp. Nhưng bất kỳ sự không phù hợp sẽ được trình biên dịch chú ý đến bạn.
Đây là đoạn mã của tôi để kích hoạt sự kiện nhấp và chuyển giá trị sang dạng khác:
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();
}
}
Ví dụ, giả sử DataGridView
có các cột như được đưa ra dưới đây và các mục ràng buộc dữ liệu của nó thuộc loại PrimalPallet
bạn có thể sử dụng giải pháp được đưa ra dưới đây.
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.
}
}
}
Đó là an toàn hơn để cột truy cập trực tiếp hơn là sử dụng dataGridView1.Columns["MyColumnName"]
và không có nhu cầu để phân tích sender
đến DataGridView
khi nó không cần thiết.
tốt thôi, tôi sẽ cắn.
bạn sẽ cần phải làm một cái gì đó như thế này - rõ ràng là tất cả siêu dữ liệu của nó.
button.Click += new ButtonClickyHandlerType(IClicked_My_Button_method)
rằng "móc nối" phương thức IClicky_My_Button_method cho đến sự kiện Click của nút. Bây giờ, mỗi khi sự kiện được "bắn" từ bên trong lớp chủ sở hữu, phương thức của chúng tôi cũng sẽ bị hủy.
Trong IClicky_MyButton_method, bạn chỉ cần đặt bất cứ điều gì bạn muốn xảy ra khi bạn nhấp vào nó.
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.
}
Các chi tiết thực tế ở đây tùy thuộc vào bạn, nhưng nếu có bất cứ điều gì khác bạn đang thiếu về mặt khái niệm hãy cho tôi biết và tôi sẽ cố gắng giúp đỡ.
Hầu hết các giải pháp được bình chọn là sai, vì không thể làm việc với một vài nút trong một hàng.
Giải pháp tốt nhất sẽ là đoạn mã sau:
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");
}
}
chỉ cần thêm ToList()
phương thức vào cuối danh sách của bạn, nơi liên kết với datagridview DataSource:
dataGridView1.DataSource = MyList.ToList();
Bạn có thể thử cái này, bạn sẽ không quan tâm nhiều đến thứ tự của các cột.
private void TheGrid_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (TheGrid.Columns[e.ColumnIndex].HeaderText == "Edit")
{
// to do: edit actions here
MessageBox.Show("Edit");
}
}
Ví dụ cho sự kiện ClickCell trong Windows Forms.
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);
}
Trân trọng :)
Trong trường hợp ai đó đang sử dụng C # (hoặc xem Lưu ý về VB.NET bên dưới) và đã đạt đến điểm này, nhưng vẫn bị kẹt, vui lòng đọc tiếp.
Câu trả lời của Joshua đã giúp tôi, nhưng không phải là tất cả. Bạn sẽ nhận thấy Peter hỏi "Bạn sẽ lấy nút từ đâu?", Nhưng không được trả lời.
Cách duy nhất nó hoạt động với tôi là thực hiện một trong những cách sau để thêm trình xử lý sự kiện của tôi (sau khi đặt DataSource của DataGridView cho DataTable của tôi và sau khi thêm DataGridViewButtonColumn vào DataGridView):
Hoặc:
dataGridView1.CellClick += new DataGridViewCellEventHandler(dataGridView1_CellClick);
hoặc là:
dataGridView1.CellContentClick += new DataGridViewCellEventHandler(dataGridView1_CellContentClick);
Và sau đó thêm phương thức xử lý (dataGridView1_CellClick hoặc dataGridView1_CellContentClick) được hiển thị trong các câu trả lời khác nhau ở trên.
Lưu ý: VB.NET khác với C # về mặt này, vì chúng ta chỉ cần thêm mệnh đề Handles vào chữ ký của phương thức hoặc đưa ra câu lệnh AddHandler như được mô tả trong tài liệu " Cách gọi: Trình xử lý sự kiện trong Visual Basic " của tài liệu Microsoft
Bạn sẽ thêm cột nút như thế này trong dataGridView của bạn
DataGridViewButtonColumn mButtonColumn0 = new DataGridViewButtonColumn();
mButtonColumn0.Name = "ColumnA";
mButtonColumn0.Text = "ColumnA";
if (dataGridView.Columns["ColumnA"] == null)
{
dataGridView.Columns.Insert(2, mButtonColumn0);
}
Sau đó, bạn có thể thêm một số hành động bên trong sự kiện nhấp chuột di động. Tôi thấy đây là cách dễ nhất để làm điều đó.
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.
}
}
Tôi thấy rằng sự kiện Cell Click được đăng ký tự động thường xuyên. Vì vậy, tôi không cần mã này dưới đây. Tuy nhiên, nếu sự kiện nhấp vào ô của bạn không được đăng ký, thì hãy thêm dòng mã này cho dataGridView của bạn.
this.dataGridView.CellClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView_CellClick);