Как обработать событие нажатия в столбце кнопки в Datagridview? - PullRequest
121 голосов
/ 26 августа 2010

Я занимаюсь разработкой приложения для Windows на C #. Я использую DataGridView для отображения данных. Я добавил столбец кнопки в этом. Я хочу знать, как я могу обработать событие нажатия на эту кнопку в DataGridView.

Ответы [ 14 ]

227 голосов
/ 03 декабря 2012

Вы добавили кнопку в DataGridView и хотите запустить какой-нибудь код при нажатии.
Легко peasy - просто выполните следующие действия:

Этикет:

Во-первых, вот что НЕ сделать:

Я бы не советовал в некоторых других ответах здесь и даже в документации на MSDN жестко закодировать индекс столбца или имя столбца, чтобы определить, была ли нажата кнопка. Событие click регистрируется для всей сетки, так что каким-то образом вам нужно определить, что кнопка была нажата, но вы не должны этого делать, предполагая, что ваша кнопка живет с определенным именем столбца или индексом ... есть более простой способ ...

Кроме того, будьте осторожны, какое событие вы хотите обработать. Опять же, документация и многие примеры ошибаются. Большинство примеров обрабатывают событие CellClick, которое вызовет:

при нажатии любой части ячейки.

... но также срабатывает при каждом щелчке по заголовку row . Это требует добавления дополнительного кода, чтобы просто определить, меньше ли значение e.RowIndex, чем 0

.

Вместо этого обработайте CellContentClick, который происходит только:

при нажатии на содержимое в ячейке

По какой-либо причине заголовок столбца также считается «содержимым» внутри ячейки, поэтому нам все равно придется проверить это ниже.

Dos:

Итак, вот что вы должны сделать:

Сначала приведите отправителя к DataGridView, чтобы раскрыть его внутренние свойства во время разработки. Вы можете изменить тип параметра, но иногда это может усложнить добавление или удаление обработчиков.

Далее, чтобы увидеть, была ли нажата кнопка, просто убедитесь, что столбец, вызывающий событие, имеет тип DataGridViewButtonColumn. Поскольку мы уже приводим отправителя к типу DataGridView, мы можем получить коллекцию Columns и выбрать текущий столбец, используя e.ColumnIndex. Затем проверьте, имеет ли этот объект тип DataGridViewButtonColumn.

Конечно, если вам нужно различать несколько кнопок на сетке, вы можете выбрать на основе имени столбца или индекса, но это не должно быть вашей первой проверкой. Всегда убедитесь, что кнопка была нажата в первую очередь, а затем обрабатывать что-либо еще соответствующим образом. В большинстве случаев, когда у вас есть только одна кнопка на сетке, вы можете сразу перейти к гонкам.

Собираем все вместе:

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. Вы не можете добавить его в саму 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

Вот и все. Никогда не трогай это снова. Убедитесь, что ваш DataGrid имеет тип DataGridViewExt, который должен работать точно так же, как DataGridView. Кроме того, это также вызовет дополнительное событие, которое вы можете обработать следующим образом:

Private Sub DataGridView1_ButtonClick(sender As DataGridView, e As DataGridViewCellEventArgs) _
                                      Handles DataGridView1.CellButtonClick
    'TODO - Button Clicked - Execute Code Here
End Sub
15 голосов
/ 26 августа 2010

Здесь полностью дан ответ для WinForms: DataGridViewButtonColumn Class

и здесь: Как: отвечать на события кнопки в элементе управления GridView

для Asp.Net в зависимости от элемента управления, который вы на самом деле используете.(Ваш вопрос говорит о DataGrid, но вы разрабатываете приложение для Windows, поэтому используемый вами элемент управления - это DataGridView ...)

9 голосов
/ 11 июня 2012

Вот лучший ответ:

Невозможно реализовать событие нажатия кнопки для ячеек кнопки в DataGridViewButtonColumn. Вместо этого вы используете событие CellClicked объекта DataGridView и определяете, произошло ли событие для ячейки в вашем 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);
  }
}

найдено здесь: событие нажатия кнопки в сетке данных

8 голосов
/ 28 августа 2010

Это решает мою проблему.

private void dataGridViewName_CellContentClick(object sender, DataGridViewCellEventArgs e)
    {
        //Your code
    }
4 голосов
/ 27 февраля 2015

Немного опоздал к таблице здесь, но в 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();
        }
    }
}

Обратите внимание, что прелесть этого в том, что любые изменения имени будут отслеживаться компилятором. Если вы индексируете текстовое имя, которое изменяется или неправильно пишется с заглавной буквы, вы столкнетесь с проблемами во время выполнения. Здесь вы фактически используете имя объекта, который дизайнер создает на основе предоставленного вами имени. Но любое несоответствие будет доведено до вашего сведения компилятором.

2 голосов
/ 28 декабря 2014

Вот мой фрагмент кода для запуска события click и передачи значения в другую форму:

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();

        }
    }
1 голос
/ 08 февраля 2018

Предположим, например, что DataGridView имеет столбцы, как указано ниже, и элементы, связанные с данными, имеют тип PrimalPallet, вы можете использовать решение, указанное ниже.

enter image description here

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, так как он не нужен.

0 голосов
/ 25 ноября 2018

Вы добавите столбец кнопки, как это в вашем 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);
0 голосов
/ 22 марта 2018

В случае, если кто-то использует C # (или см. Примечание о VB.NET ниже) и достиг этой точки, но все еще застрял, пожалуйста, продолжайте читать.

Ответ Джошуа помог мне, но не полностью,Вы заметите, что Питер спросил: «Откуда ты взял бы кнопку?», Но остался без ответа.

Единственный способ, которым он работал для меня, - это сделать одно из следующего, чтобы добавить обработчик событий (после настройки моего DataGridViewDataSource в мой DataTable и после добавления DataGridViewButtonColumn в DataGridView):

Либо:

dataGridView1.CellClick += new DataGridViewCellEventHandler(dataGridView1_CellClick);

или:

dataGridView1.CellContentClick += new DataGridViewCellEventHandler(dataGridView1_CellContentClick);

И затем добавьте метод обработчика (либоdataGridView1_CellClick или dataGridView1_CellContentClick), показанные в различных ответах выше.

Примечание: VB.NET отличается от C # в этом отношении, потому что мы можем просто добавить предложение Handles к сигнатуре нашего метода или выполнить оператор AddHandler, как описано вдокумента Microsoft " Как: вызвать обработчик событий в Visual Basic "

0 голосов
/ 16 ноября 2017

Например, для события ClickCell в 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);
                }

С уважением:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...