it-swarm.com.ru

Как обработать событие нажатия в столбце кнопки в Datagridview?

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

115
Himadri

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

Этикет:

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

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

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

когда любая часть ячейки нажата.

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

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

когда щелкается контент внутри ячейки

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

Dos:

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

Во-первых, cast отправитель набирает 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
217
KyleMit

Это полностью отвечено здесь для WinForms: DataGridViewButtonColumn Class

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

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

15
David

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

Вы не можете реализовать событие нажатия кнопки для ячеек кнопки в 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);
  }
}

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

9
TechStuffBC

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

private void dataGridViewName_CellContentClick(object sender, DataGridViewCellEventArgs e)
    {
        //Your code
    }
8
Himadri

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

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

4
Arunas

Вот мой фрагмент кода для запуска события 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();

        }
    }
2
newComer

Предположим, например, что 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, так как он не нужен. 

1
Ryfcia

Решение с большинством голосов неверно, так как не может работать с несколькими кнопками в одном ряду.

Лучшим решением будет следующий код:

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");
            }
        }
0
Andrew

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

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

0
Diego Mauricio Guerrero

Вы можете попробовать это, вы не будете беспокоиться о порядке столбцов.

private void TheGrid_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
    if (TheGrid.Columns[e.ColumnIndex].HeaderText == "Edit")
    {
        // to do: edit actions here
        MessageBox.Show("Edit");
    }
}
0
JL Dajoyag

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

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

Единственный способ, которым он работал для меня, - это сделать одно из следующего, чтобы добавить обработчик событий (после установки DataSridView моего DataGridView в мой 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
clairestreb

хорошо, я укушу.

вам нужно сделать что-то вроде этого - очевидно, все это метакод.

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.
}

Фактические детали здесь до вас, но если есть что-то еще, что вы упускаете концептуально, дайте мне знать, и я постараюсь помочь.

0
Joshua Evensen

Вы добавите столбец кнопки, как это в вашем 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
auto9817

просто добавьте метод ToList() в конец списка, где привязка к источнику данных datagridview:

dataGridView1.DataSource = MyList.ToList();
0
nima khankhanizadeh