簡體   English   中英

Datagridview錯誤C#后,CurrentCellDirtyStateChanged不起作用

[英]CurrentCellDirtyStateChanged doesn't work after a datagridview error C#

我有一個datagridview從數據庫加載數據。 該datagridview有2個int列,我在其中插入數字。 而且,如果我在兩列之一中插入數字,那么還會有另外兩列單元格自動填充數學運算的結果。 相反,如果我插入字母,則datagridview會顯示錯誤。

問題是:每當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;                               
        }

提前致謝!。

從發布的代碼看來,正在使用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;
}

將以上DataTableExpression列用於Total可以消除對CurrentCellDirtyStateChanged事件的需要。 在所有其他單元格都有數據之后, Total s列單元格將自動更新。

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

我猜想,如果您“捕獲”用戶的KeyPressed事件並直接忽略任何無效字符,則可能會更輕松,更友好。 示例:如果捕獲到用戶KeyPressed輸入,並且該輸入位於應為數字且不是數字或小數點的列之一中,則忽略該輸入。 使用此實現,用戶將無法鍵入數字和小數點以外的字符。 這將防止DataError被那些列拋出。

為此,您需要為目標列中的單元格實施一個“ KeyPressed”事件。 觸發此事件時,它可以檢查並忽略任何無效字符。 需要連接的事件是DataGridViews EditingControlShowing事件。 用戶鍵入單元格時將觸發此事件。 首先,檢查用戶鍵入的單元格是否在數字列之一中。 如果是,那么您只需要向該單元格注冊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事件。 在這種情況下,將檢查它是否為數字列,然后注冊KeyPressed事件以對該單元觸發。

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是否與數據綁定,以上兩種方法均應起作用。 希望這可以幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM