Подтвердить что ты не робот

Как определить событие EventGridView CheckBox?

У меня есть приложение winforms и вы хотите запустить какой-либо код, когда флажок, встроенный в элемент управления DataGridView, проверяется/не проверяется. Каждое событие, которое я пробовал либо

  • Триггеры, как только нажимается CheckBox, но до того, как оно будет изменено, или
  • Триггеры только один раз, когда CheckBox теряет фокус

Я не могу найти событие, которое срабатывает сразу после изменения состояния проверки.


Edit:

То, что я пытаюсь достичь, заключается в том, что когда измененное состояние CheckBox в одном DataGridView изменяется, данные в двух других DataGridView изменяются. Но все события, которые я использовал, данные в других сетках меняются только после того, как CheckBox в первом DataGridView теряет фокус.

4b9b3361

Ответ 1

Чтобы обработать событие DatGridView CheckedChanged, вы должны сначала запустить CellContentClick (который не имеет текущего состояния CheckBox es!), а затем вызвать CommitEdit. Это, в свою очередь, вызовет событие CellValueChanged, которое вы можете использовать для выполнения своей работы. Это недосмотр Microsoft. Сделайте что-нибудь вроде следующего...

private void dataGridViewSites_CellContentClick(object sender, 
    DataGridViewCellEventArgs e)
{
    dataGridViewSites.CommitEdit(DataGridViewDataErrorContexts.Commit);
}

/// <summary>
/// Works with the above.
/// </summary>
private void dataGridViewSites_CellValueChanged(object sender, 
    DataGridViewCellEventArgs e)
{
    UpdateDataGridViewSite();
}

Надеюсь, это поможет.

P.S. Проверьте эту статью https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.currentcelldirtystatechanged(v=vs.110).aspx

Ответ 2

Я нашел решение @Killercam для работы, но было немного изворотливым, если пользователь дважды щелкнул слишком быстро. Не уверен, что другие обнаружили, что дело. Я нашел другое решение здесь.

Он использует datagrid CellValueChanged и CellMouseUp. Чанхун объясняет, что

"Причиной этого является событие OnCellvalueChanged, которое не запускается до тех пор, пока DataGridView не подумает, что вы завершили редактирование. Это создает смысл для столбца TextBox, поскольку OnCellvalueChanged не будет [беспокоить], чтобы стрелять для каждого нажатия клавиши, но это не делает [смысл] для CheckBox."

Здесь он находится в действии из своего примера:

private void myDataGrid_OnCellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    if (e.ColumnIndex == myCheckBoxColumn.Index && e.RowIndex != -1)
    {
        // Handle checkbox state change here
    }
}

И код, чтобы установить флажок, он будет редактироваться при нажатии, вместо того, чтобы ждать, пока пользователь покинет поле:

private void myDataGrid_OnCellMouseUp(object sender,DataGridViewCellMouseEventArgs e)
{
    // End of edition on each click on column of checkbox
    if (e.ColumnIndex == myCheckBoxColumn.Index && e.RowIndex != -1)
    {
        myDataGrid.EndEdit();
    }
}

Ответ 3

Решение

jsturtevants отлично работало. Однако я решил сделать обработку в событии EndEdit. Я предпочитаю этот подход (в моем приложении), потому что, в отличие от события CellValueChanged, событие EndEdit не срабатывает, когда вы заполняете сетку.

Вот мой код (часть которого украдена у jsturtevant:

private void gridCategories_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    if (e.ColumnIndex == gridCategories.Columns["AddCategory"].Index)
    {
        //do some stuff
    }
}



private void gridCategories_CellMouseUp(object sender, DataGridViewCellMouseEventArgs e)
{
    if (e.ColumnIndex == gridCategories.Columns["AddCategory"].Index)
    {
        gridCategories.EndEdit();
    }
}

Ответ 4

Это также относится к активации клавиатуры.

    private void dgvApps_CellContentClick(object sender, DataGridViewCellEventArgs e)
    {
        if(dgvApps.CurrentCell.GetType() == typeof(DataGridViewCheckBoxCell))
        {
            if (dgvApps.CurrentCell.IsInEditMode)
            {
                if (dgvApps.IsCurrentCellDirty)
                {
                    dgvApps.EndEdit();
                }
            }
        }
    }


    private void dgvApps_CellValueChanged(object sender, DataGridViewCellEventArgs e)
    {
          // handle value changed.....
    }

Ответ 5

Вот какой код:

private void dgvStandingOrder_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
    if (dgvStandingOrder.Columns[e.ColumnIndex].Name == "IsSelected" && dgvStandingOrder.CurrentCell is DataGridViewCheckBoxCell)
    {
        bool isChecked = (bool)dgvStandingOrder[e.ColumnIndex, e.RowIndex].EditedFormattedValue;
        if (isChecked == false)
        {
            dgvStandingOrder.Rows[e.RowIndex].Cells["Status"].Value = "";
        }
        dgvStandingOrder.EndEdit();
    }
}

private void dgvStandingOrder_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{

    dgvStandingOrder.CommitEdit(DataGridViewDataErrorContexts.Commit);
}

private void dgvStandingOrder_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
    if (dgvStandingOrder.CurrentCell is DataGridViewCheckBoxCell)
    {
        dgvStandingOrder.CommitEdit(DataGridViewDataErrorContexts.Commit);
    }
}

Ответ 6

после Killercam'answer, My code

private void dgvProducts_CellContentClick(object sender, DataGridViewCellEventArgs e)
    {
        dgvProducts.CommitEdit(DataGridViewDataErrorContexts.Commit);
    }

и:

private void dgvProducts_CellValueChanged(object sender, DataGridViewCellEventArgs e)
    {
        if (dgvProducts.DataSource != null)
        {
            if (dgvProducts.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString() == "True")
            {
                //do something
            }
            else
            {
               //do something
            }
        }
    }

Ответ 7

Все о редактировании ячейки, проблема, которая является ячейкой, фактически не редактировалась, поэтому вам нужно сохранить изменения ячейки или строки, чтобы получить событие, когда вы нажмете этот флажок, чтобы вы могли использовать эту функция:

datagridview.CommitEdit(DataGridViewDataErrorContexts.CurrentCellChange)

с этим вы можете использовать его даже с другим событием.

Ответ 8

Я нашел более простой ответ на эту проблему. Я просто использую обратную логику. Код находится в VB, но он не сильно отличается от С#.

 Private Sub DataGridView1_CellContentClick(sender As Object, e As 
 DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick

    Dim _ColumnIndex As Integer = e.ColumnIndex
    Dim _RowIndex As Integer = e.RowIndex

    'Uses reverse logic for current cell because checkbox checked occures 
     'after click
    'If you know current state is False then logic dictates that a click 
     'event will set it true
    'With these 2 check boxes only one can be true while both can be off

    If DataGridView1.Rows(_RowIndex).Cells("Column2").Value = False And 
       DataGridView1.Rows(_RowIndex).Cells("Column3").Value = True Then
        DataGridView1.Rows(_RowIndex).Cells("Column3").Value = False
    End If

    If DataGridView1.Rows(_RowIndex).Cells("Column3").Value = False And 
    DataGridView1.Rows(_RowIndex).Cells("Column2").Value = True Then
        DataGridView1.Rows(_RowIndex).Cells("Column2").Value = False
    End If


End Sub

Одна из лучших вещей в этом случае не нужна для нескольких событий.

Ответ 9

Что сработало для меня, было CurrentCellDirtyStateChanged в сочетании с datagridView1.EndEdit()

private void dataGridView1_CurrentCellDirtyStateChanged( object sender, EventArgs e ) {
    if ( dataGridView1.CurrentCell is DataGridViewCheckBoxCell ) {
        DataGridViewCheckBoxCell cb = (DataGridViewCheckBoxCell)dataGridView1.CurrentCell;
        if ( (byte)cb.Value == 1 ) {
            dataGridView1.CurrentRow.Cells["time_loadedCol"].Value = DateTime.Now.ToString();
        }
    }
    dataGridView1.EndEdit();
}

Ответ 10

Код будет зацикливаться в DataGridView и проверяет, проверен ли CheckBox Column

private void dgv1_CellMouseUp(object sender, DataGridViewCellMouseEventArgs e)
{
    if (e.ColumnIndex == 0 && e.RowIndex > -1)
    {
        dgv1.CommitEdit(DataGridViewDataErrorContexts.Commit);
        var i = 0;
        foreach (DataGridViewRow row in dgv1.Rows)
        {
            if (Convert.ToBoolean(row.Cells[0].Value))
            {
                i++;
            }
        }

        //Enable Button1 if Checkbox is Checked
        if (i > 0)
        {
            Button1.Enabled = true;
        }
        else
        {
            Button1.Enabled = false;
        }
    }
}

Ответ 11

В случае CellContentClick вы можете использовать эту стратегию:

private void myDataGrid_CellContentClick(object sender, DataGridViewCellEventArgs e)
{    
    if (e.ColumnIndex == 2)//set your checkbox column index instead of 2
    {   //When you check
        if (Convert.ToBoolean(myDataGrid.Rows[e.RowIndex].Cells[2].EditedFormattedValue) == true)
        {
            //EXAMPLE OF OTHER CODE
            myDataGrid.Rows[e.RowIndex].Cells[5].Value = DateTime.Now.ToShortDateString();

            //SET BY CODE THE CHECK BOX
            myDataGrid.Rows[e.RowIndex].Cells[2].Value = 1;
        }
        else //When you decheck
        {
            myDataGrid.Rows[e.RowIndex].Cells[5].Value = String.Empty;

            //SET BY CODE THE CHECK BOX
            myDataGrid.Rows[e.RowIndex].Cells[2].Value = 0;
        }
    }
}

Ответ 12

Чтобы сделать это при использовании devexpress xtragrid, необходимо обработать событие EditValueChanged соответствующего элемента репозитория, как описано здесь. Также важно вызвать метод gridView1.PostEditor(), чтобы гарантировать, что измененное значение было опубликовано. Вот реализация:

        private void RepositoryItemCheckEdit1_EditValueChanged(object sender, System.EventArgs e)
        {
            gridView3.PostEditor();

            var isNoneOfTheAboveChecked = false;

            for (int i = 0; i < gridView3.DataRowCount; i++)
            {
                if ((bool) (gridView3.GetRowCellValue(i, "NoneOfTheAbove")) && (bool) (gridView3.GetRowCellValue(i, "Answer")))
                {
                    isNoneOfTheAboveChecked = true;
                    break;
                }
            }

            if (isNoneOfTheAboveChecked)
            {
                for (int i = 0; i < gridView3.DataRowCount; i++)
                {
                    if (!((bool)(gridView3.GetRowCellValue(i, "NoneOfTheAbove"))))
                    {
                        gridView3.SetRowCellValue(i, "Answer", false);
                    }
                }
            }
        }

Обратите внимание, что поскольку xtragrid не предоставляет перечислитель, необходимо использовать цикл for для итерации по строкам.

Ответ 13

Я нашел более простой ответ на эту проблему. Я просто использую обратную логику. Код находится в VB, но он не сильно отличается от С#.

 Private Sub DataGridView1_CellContentClick(sender As Object, e As 
 DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick

    Dim _RowIndex As Integer = e.RowIndex

    'Uses reverse logic for current cell because checkbox checked occures 
     'after click
    'If you know current state is False then logic dictates that a click 
     'event will set it true
    'With these 2 check boxes only one can be true while both can be off

    If DataGridView1.Rows(_RowIndex).Cells("Column2").Value = False And 
       DataGridView1.Rows(_RowIndex).Cells("Column3").Value = True Then
        DataGridView1.Rows(_RowIndex).Cells("Column3").Value = False
    End If

    If DataGridView1.Rows(_RowIndex).Cells("Column3").Value = False And 
    DataGridView1.Rows(_RowIndex).Cells("Column2").Value = True Then
        DataGridView1.Rows(_RowIndex).Cells("Column2").Value = False
    End If


End Sub

Одна из лучших вещей в этом случае не нужна для нескольких событий.

Ответ 14

Удаление фокуса после изменения значения ячейки позволяет обновлять значения в DataGridView. Удалите фокус, установив CurrentCell в значение null.

private void DataGridView1OnCellValueChanged(object sender, DataGridViewCellEventArgs dataGridViewCellEventArgs)
{
    // Remove focus
    dataGridView1.CurrentCell = null;
    // Put in updates
    Update();
}

private void DataGridView1OnCurrentCellDirtyStateChanged(object sender, EventArgs eventArgs)
{
    if (dataGridView1.IsCurrentCellDirty)
    {
        dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
    }

}

Ответ 15

Вы можете заставить ячейку зафиксировать значение, как только вы установите флажок, а затем поймаете событие CellValueChanged. CurrentCellDirtyStateChanged срабатывает, как только вы нажимаете этот флажок.

Следующий код работает для меня:

private void grid_CurrentCellDirtyStateChanged(object sender, EventArgs e)
    {
        SendKeys.Send("{tab}");
    }

Затем вы можете вставить свой код в событие CellValueChanged.

Ответ 16

Я попробовал некоторые ответы отсюда, но у меня всегда были какие-то проблемы (например, двойной щелчок или использование клавиатуры). Итак, я объединил некоторые из них и получил последовательное поведение (оно не идеально, но работает правильно).

void gridView_CellContentClick(object sender, DataGridViewCellEventArgs e) {
  if(gridView.CurrentCell.GetType() != typeof(DataGridViewCheckBoxCell))
    return;
  if(!gridView.CurrentCell.IsInEditMode)
    return;
  if(!gridView.IsCurrentCellDirty)
    return;
  gridView.EndEdit();
}

void gridView_CellMouseUp(object sender, DataGridViewCellMouseEventArgs e) {
  if(e.ColumnIndex == gridView.Columns["cFlag"].Index && e.RowIndex >= 0)
    gridView.EndEdit();
}

void gridView_CellValueChanged(object sender, DataGridViewCellEventArgs e) {
  if(e.ColumnIndex != gridView.Columns["cFlag"].Index || e.RowIndex < 0)
    return;

  // Do your stuff here.

}