Я делаю a 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 входит как пустой указатель (предложение адреса текущей ячейки является неправильным так или иначе, но я не попытался вывести то значение), подразумевать, что путь не работает вообще.
В основном, как я получаю "правильный" адрес с правильным булевым значением так, чтобы мой алгоритм зеркального отражения работал?
В конечном итоге это произошло событие 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
, оно сработает только ПОСЛЕ того, как вы покинете ячейку. Я не знаю, почему именно (учитывая, что это флажок, разве это не «готово» сразу?), Но вот что происходит. И код, как указано выше, работает в том смысле, что изменения флажка перемещаются СРАЗУ при нажатии на него. Так что работает.
Вы можете использовать событие 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";
}
}