2017-05-27 21 views
0

我有一個datagridview我從數據庫中加載數據。該datagridview有2個int列,我插入數字。而且,如果我在兩列之一中插入一個數字,還有兩列單元格會自動填充數學運算的結果。相反,如果我插入一個字母,datagridview會顯示一個錯誤。DataGridview錯誤後CurrentCellDirtyStateChanged不工作C#

問題是這樣的:每當datagridview顯示錯誤時,單擊錯誤消息框中的「確定」後,我可以繼續編輯單元格,但CurrentCellDirtyStateChanged事件不起作用。因此其他兩列單元格不會自動填充。我需要他們在顯示錯誤後自動填寫。

這是我的代碼:

private void dgvReciboPagoSalario_DataError(object sender, DataGridViewDataErrorEventArgs e) 

    { 
     e.ThrowException = false; 

     string Error = "Error: La columna " + 
      dgvReciboPagoSalario.Columns[e.ColumnIndex].HeaderText + 
      " es de tipo numérico"; 

     DialogResult DR= MessageBox.Show(Error, "Error", 
      MessageBoxButtons.OK, MessageBoxIcon.Error); 

     e.Cancel = false; 
    } 

這是CurrentCellDirtyStateChanged事件:

private void dgvReciboPagoSalario_CurrentCellDirtyStateChanged(object sender, EventArgs e) 
    {//modificar campos de dgv al mismo tiempo que cambio otro 
     int HO = 0; 
     int HF = 0; 
     long SXH = 0; 
     long Subtotal = 0; 
     long DeduccionesPrestamo = 0; 
     long DeduccionesCCSS = 0; 
     long Total = 0; 

     if (dgvReciboPagoSalario.IsCurrentCellDirty) 
     { 


      dgvReciboPagoSalario.CommitEdit(DataGridViewDataErrorContexts.Commit); 


      if (!string.IsNullOrEmpty(dgvReciboPagoSalario.CurrentRow.Cells["Horas Ordinarias"].Value.ToString())) 
      { 
       HO = Convert.ToInt32(dgvReciboPagoSalario.CurrentRow.Cells["Horas Ordinarias"].Value); 
      } 


      if (!string.IsNullOrEmpty(dgvReciboPagoSalario.CurrentRow.Cells["Horas Feriado"].Value.ToString())) 
      { 
       HF = Convert.ToInt32(dgvReciboPagoSalario.CurrentRow.Cells["Horas Feriado"].Value); 
      } 

      SXH = Convert.ToInt64(dgvReciboPagoSalario.CurrentRow.Cells["Salario por Hora"].Value); 

      Subtotal = ((HO * SXH) + ((SXH * 2) * HF)); 

      dgvReciboPagoSalario.CurrentRow.Cells["Subtotal Recibido"].Value = Subtotal; 


      if (!string.IsNullOrEmpty(dgvReciboPagoSalario.CurrentRow.Cells["Deducciones Préstamo"].Value.ToString())) 
      { 
       DeduccionesPrestamo = Convert.ToInt64(dgvReciboPagoSalario.CurrentRow.Cells["Deducciones Préstamo"].Value); 
      } 

      DeduccionesCCSS = Convert.ToInt64(dgvReciboPagoSalario.CurrentRow.Cells["Deducciones CCSS"].Value); 

      Total = (Subtotal - (DeduccionesCCSS + DeduccionesPrestamo)); 

      dgvReciboPagoSalario.CurrentRow.Cells["Total Recibido"].Value = Total;        
     } 

在此先感謝!

回答

0

從發佈的代碼看來,它使用CurrentCellDirtyStateChanged事件來設置其他列中值的Total Recibido列。這將起作用,但是如果您要使用DataTable並將Total Recibido列設置爲表格中當前單元格的Expression,則不需要使用CurrentCellDirtyStateChanged事件來處理此問題。

例如,在發佈的代碼之後,使用DataTableTotal Recibido列可能的Expression可能如下所示。添加的最後一列是Total列的Expression

private DataTable GetDT() { 
    DataTable dt = new DataTable(); 
    dt.Columns.Add("Name", typeof(string)); 
    dt.Columns.Add("OrdinaryHours", typeof(double)); 
    dt.Columns.Add("HourlyWage", typeof(double)); 
    dt.Columns.Add("HolidayHours", typeof(double)); 
    dt.Columns.Add("CCSSDeductions", typeof(double)); 
    dt.Columns.Add("LoanDeductions", typeof(double)); 
    DataColumn dc = new DataColumn("Total", typeof(double)); 
    dc.Expression = "((OrdinaryHours * HourlyWage) + (HourlyWage * 2) * HolidayHours) - (CCSSDeductions + LoanDeductions)"; 
    dt.Columns.Add(dc); 
    return dt; 
} 

與用於Total秒的Expression柱使用上述DataTable將消除對CurrentCellDirtyStateChanged事件的需要。所有其他單元格都有數據後,將自動更新Total的列單元格。

此外,從帖子看來,你沒有趕上這個DataError這是一個問題恕我直言。由於所討論的列是數字類型(int,double..etc),因此當用戶鍵入字符而不是數字並嘗試離開單元格時,將引發DataError

我猜測如果你「捕捉」了用戶KeyPressed事件並簡單地忽略任何無效字符,它可能會更容易,更方便用戶使用。示例:如果您捕獲了用戶KeyPressed輸入,並且它在其中一個列中應該是數字並且它不是數字或小數點,則忽略該輸入。在這個實現中,用戶將不能輸入數字和小數點以外的字符。這將防止DataError對這些列引發。

爲了實現這個目標,您需要爲目標列中的單元格實施「KeyPressed」事件。當這個事件觸發時,它可以檢查並忽略任何無效的字符。需要連線的事件是DataGridViewsEditingControlShowing事件。當用戶輸入單元格時,此事件將會觸發。首先,檢查用戶輸入的單元格是否在列號中的某一列中。如果是,那麼你只需要註冊KeyPressed事件到該單元格。然後KeyPressed事件將被觸發,您可以檢查正確的字符值。

下面是這個KeyPressed事件可能看起來像什麼樣子的一個例子。

private void DoubleColumn_KeyPress(object sender, KeyPressEventArgs e) { 
    // if the key pressed is not a control key or a digit or decimal - then ignore this character 
    if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) && e.KeyChar != '.') { 
    e.Handled = true; 
    } 
    // check for multiple decimal points as only one is valid 
    if (e.KeyChar == '.' && (sender as TextBox).Text.IndexOf('.') > -1) { 
    e.Handled = true; 
    } 
} 

然後,要使用此事件,我們只需在用戶鍵入數值列單元格時向單元註冊事件。此事件是EditingControlShowing事件。在這種情況下,將進行檢查以查看它是否爲數字列,然後註冊要爲該單元格觸發的事件。無論

private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) { 
    e.Control.KeyPress -= new KeyPressEventHandler(DoubleColumn_KeyPress); 
    if (dataGridView1.CurrentCell.ColumnIndex == 1 || dataGridView1.CurrentCell.ColumnIndex == 2 || 
     dataGridView1.CurrentCell.ColumnIndex == 3 || dataGridView1.CurrentCell.ColumnIndex == 4 || 
     dataGridView1.CurrentCell.ColumnIndex == 5) { 
    e.Control.KeyPress += new KeyPressEventHandler(DoubleColumn_KeyPress); 
    } 
} 

以上兩種方法應該工作,如果是DataGridView數據結合或不。希望這可以幫助。