2010-05-21 54 views
6

我正在製作一個DataGridView,其中包含一系列複選框,並在水平和垂直方向使用相同的標籤。任何標籤都是相同的,複選框將處於非活動狀態,我只希望每個組合的兩個「檢查」中的一個有效。下面的屏幕截圖顯示了我擁有的內容: DataGridView http://i46.tinypic.com/2e4m3pz.pngDataGridView複選框事件

任何在下半部分檢查的東西,我都需要在上面檢查聯合國檢查。因此,如果選擇[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作爲空值(表明當前單元格地址錯誤,但我沒有嘗試將該值取出),如何獲取當前單元格,這意味着該路徑不是「根本不工作。

基本上,我如何獲得正確的布爾值的「正確的」地址,以便我的翻轉算法將工作?

回答

16

歸根結底,這是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事件,則它僅在您離開單元后觸發。我不知道爲什麼(考慮到它是一個複選框,是不是立即「完成」),但這就是發生了什麼。而上面的代碼工作,因爲點擊它時,複選框變成RIGHT。所以它工作。

+0

是的! ......我的搜尋結束了......我現在可以過得幸福快樂。謝謝。 – zmaster 2012-12-11 09:29:39

2

您可以使用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

不幸的是'CellValidating'事件只在我關閉單元格時觸發,而不是單擊複選框並切換狀態。 – 2010-05-22 14:16:38

0

我發現的最簡單的方法是:

  • 寄存器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 
    } 
}