События DataGridView CheckBox - PullRequest
6 голосов
/ 22 мая 2010

Я делаю DataGridView с рядом флажков с одинаковыми метками по горизонтали и вертикали.Любые метки, которые совпадают, флажки будут неактивными, и я хочу, чтобы только одна из двух «проверок» для каждой комбинации была действительной.На следующем снимке экрана показано, что у меня есть: DataGridView http://i46.tinypic.com/2e4m3pz.png

Все, что проверено в нижней половине, я хочу, чтобы в верхней проверялось.Поэтому, если [quux, spam] (или [7, 8] для координат, начинающихся с нуля) проверено, я хочу, чтобы [spam, 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;
    }
}

/// <summary>
/// Change the corresponding checkbox to the opposite state of the current one
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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 имеет нулевое значение (предполагается, что текущий адрес ячейки неверен, но я не пытался вывести это значение), что означаетэтот путь вообще не работает.

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

Ответы [ 3 ]

16 голосов
/ 25 мая 2010

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

2 голосов
/ 22 мая 2010

Вы можете использовать событие 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";
    }
}
0 голосов
/ 11 апреля 2014

Простейший метод, который я нашел:

  • регистрация для grid_CellContentClick
  • Изучите либо все строки ячейки, используя приведенную ниже, либо только строку из обработчика событий.Мой код требовал пересоздания модели данных из всего состояния выбранных ячеек.

EditedFormattedValue - это «новое» значение ячейки и значение для чтения.

,

var colNumber=0;
foreach (var row in grid.Rows) {
   var dataGridViewCell = (DataGridViewCheckBoxCell)((DataGridViewRow)(row)).Cells[colNumber];
   if (dataGridViewCell.EditedFormattedValue) {
        // This cell is now checked - do whatever you need to with the other cells
   }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...