События DataGridView CheckBox

Я делаю a DataGridView с серией Флажков в нем с теми же маркировками горизонтально и вертикально. Любые маркировки, которые являются тем же, флажки, будут неактивны, и я только хочу, чтобы одна из двух "проверок" на каждую комбинацию была допустима. Следующий снимок экрана показывает то, что я имею: DataGridView

Что-либо это проверяется на более низкой половине, я хочу Непроверенный на верхнем. Таким образом, если [quux, спам] (или [7, 8] для основанных на нуле координат) проверяется, я хочу [спам, quux] ([8, 7]) неконтролируемый. Что я имею, до сих пор следующее:

    dgvSysGrid.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders;
    dgvSysGrid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
    string[] allsysNames = { "heya", "there", "lots", "of", "names", "foo", "bar", "quux", "spam", "eggs", "bacon" };

    // Add a column for each entry, and a row for each entry, and mark the "diagonals" as readonly
    for (int i = 0; i < allsysNames.Length; i++)
    {
        dgvSysGrid.Columns.Add(new DataGridViewCheckBoxColumn(false));
        dgvSysGrid.Columns[i].HeaderText = allsysNames[i];
        dgvSysGrid.Rows.Add();
        dgvSysGrid.Rows[i].HeaderCell.Value = allsysNames[i];
        // Mark all of the "diagonals" as unable to change
        DataGridViewCell curDiagonal = dgvSysGrid[i, i];
        curDiagonal.ReadOnly = true;
        curDiagonal.Style.BackColor = Color.Black;
        curDiagonal.Style.ForeColor = Color.Black;
    }

    // Hook up the event handler so that we can change the "corresponding" checkboxes as needed
    //dgvSysGrid.CurrentCellDirtyStateChanged += new EventHandler(dgvSysGrid_CurrentCellDirtyStateChanged);
    dgvSysGrid.CellValueChanged += new DataGridViewCellEventHandler(dgvSysGrid_CellValueChanged);

}

void dgvSysGrid_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    Point cur = new Point(e.ColumnIndex, e.RowIndex);

    // Change the diagonal checkbox to the opposite state
    DataGridViewCheckBoxCell curCell = (DataGridViewCheckBoxCell)dgvSysGrid[cur.X, cur.Y];
    DataGridViewCheckBoxCell diagCell = (DataGridViewCheckBoxCell)dgvSysGrid[cur.Y, cur.X];
    if ((bool)(curCell.Value) == true)
    {
        diagCell.Value = false;
    }
    else
    {
        diagCell.Value = true;
    }
}

/// 
/// Change the corresponding checkbox to the opposite state of the current one
/// 
/// 
/// 
void dgvSysGrid_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
    Point cur = dgvSysGrid.CurrentCellAddress;

    // Change the diagonal checkbox to the opposite state
    DataGridViewCheckBoxCell curCell = (DataGridViewCheckBoxCell)dgvSysGrid[cur.X, cur.Y];
    DataGridViewCheckBoxCell diagCell = (DataGridViewCheckBoxCell)dgvSysGrid[cur.Y, cur.X];
    if ((bool)(curCell.Value) == true)
    {
        diagCell.Value = false;
    }
    else
    {
        diagCell.Value = true;
    }
} 

Проблема возникает, то, что значение ячейки, изменяемое всегда, кажется, "один позади", где Вы на самом деле нажимаете, если я использую CellValueChanged событие, и я не уверен, как получить текущую ячейку, если я нахожусь в "грязном" состоянии, поскольку curCell входит как пустой указатель (предложение адреса текущей ячейки является неправильным так или иначе, но я не попытался вывести то значение), подразумевать, что путь не работает вообще.

В основном, как я получаю "правильный" адрес с правильным булевым значением так, чтобы мой алгоритм зеркального отражения работал?

6
задан Glorfindel 27 July 2019 в 05:36
поделиться

2 ответа

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

Фрагмент сверху и то, что я в итоге сделал, ниже:

    // Hook up the event handler so that we can change the "corresponding" checkboxes as needed
    dgvSysGrid.CurrentCellDirtyStateChanged += new EventHandler(dgvSysGrid_CurrentCellDirtyStateChanged);
    dgvSysGrid.CellValueChanged += new DataGridViewCellEventHandler(dgvSysGrid_CellValueChanged);

}

void dgvSysGrid_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    Point cur = new Point(e.ColumnIndex, e.RowIndex);

    // Change the diagonal checkbox to the opposite state
    DataGridViewCheckBoxCell curCell = (DataGridViewCheckBoxCell)dgvSysGrid[cur.X, cur.Y];
    DataGridViewCheckBoxCell diagCell = (DataGridViewCheckBoxCell)dgvSysGrid[cur.Y, cur.X];
    if ((bool)(curCell.Value) == true)
    {
        diagCell.Value = false;
    }
    else
    {
        diagCell.Value = true;
    }
}

void dgvSysGrid_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
    if (dgvSysGrid.IsCurrentCellDirty)
    {
        dgvSysGrid.CommitEdit(DataGridViewDataErrorContexts.Commit);
    }
}

По сути, все, что происходит, - это событие CurrentCellDirtyStateChanged , запускающее событие CellValueChanged , и все. Если вы просто присоедините событие CellValueChanged , оно сработает только ПОСЛЕ того, как вы покинете ячейку. Я не знаю, почему именно (учитывая, что это флажок, разве это не «готово» сразу?), Но вот что происходит. И код, как указано выше, работает в том смысле, что изменения флажка перемещаются СРАЗУ при нажатии на него. Так что работает.

16
ответ дан 8 December 2019 в 12:58
поделиться

Вы можете использовать событие CellValidating , и у e.FormattedValue будет измененное значение. Если вы выполняете некоторую проверку и не хотите, чтобы значение обновлялось, установите для e.Cancel значение true.

Вот пример со страницы FormattedValue:

private void dataGridView1_CellValidating(object sender,
    DataGridViewCellValidatingEventArgs e)
{
    dataGridView1.Rows[e.RowIndex].ErrorText = "";
    int newInteger;

    // Don't try to validate the 'new row' until finished 
    // editing since there
    // is not any point in validating its initial value.
    if (dataGridView1.Rows[e.RowIndex].IsNewRow) { return; }
    if (!int.TryParse(e.FormattedValue.ToString(),
        out newInteger) || newInteger < 0)
    {
        e.Cancel = true;
        dataGridView1.Rows[e.RowIndex].ErrorText = "the value must be a non-negative integer";
    }
}
2
ответ дан 8 December 2019 в 12:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: