2017-05-27 1 views
0

私はデータベースからデータをロードするdatagridviewを持っています。そのdatagridviewには2つのintカラムがあり、そこに数字を挿入します。また、2つの列のいずれかに数値を挿入すると、数学的演算の結果を自動的に満たす別の2つの列セルがあります。逆に、文字を挿入すると、datagridviewにエラーが表示されます。DataGridviewエラーの後にCurrentCellDirtyStateChangedが機能しないC#

この問題は、datagridviewにエラーが表示されたときにエラーメッセージボックスの「OK」をクリックした後で、セルの編集を続けることができますが、CurrentCellDirtyStateChangedイベントは機能しません。したがって、他の2つの列のセルは自動的に塗りつぶされません。そして、私はエラーが表示された後に自動的に記入する必要があります。

これは私のコードです:

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イベントがこれを処理する必要はありません。

例:投稿コードに続いて、を使用して、をTotal Recibido列に使用すると、次のようになります。追加された最後の列はTotal列のExpressionです。 CurrentCellDirtyStateChangedイベントの必要性を排除するTotal秒間Expressionカラムと上記DataTableを使用

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の列セルは、他のすべてのセルにデータがあると自動的に更新されます。

さらに、投稿から、これは問題であるDataErrorを捕まえていないように見えます。問題の列は数値型(int、double..etc)なので、ユーザーが数値の代わりに文字を入力してセルを出そうとすると、DataErrorがスローされます。

ユーザーKeyPressedのイベントを「キャッチ」して無効な文字を無視すると、より簡単で使いやすいかもしれないと推測しています。例:ユーザKeyPressedの入力を受け取り、数値でなければならない列の1つにあり、数値または小数点ではない場合は、入力を無視します。この実装では、ユーザーは数字と小数点以外の文字を入力することはできません。これにより、これらの列に対してDataErrorがスローされなくなります。

これを実行するには、ターゲット列のセルに「KeyPressed」イベントを実装する必要があります。このイベントが発生すると、無効な文字をチェックして無視できます。有線接続が必要なイベントは、DataGridViewsEditingControlShowingイベントです。このイベントは、ユーザーがセルに入力すると発生します。まず、ユーザーが入力したセルが数値列である列の1つにあるかどうかを調べるためのチェックが行われます。そうであれば、そのセルに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がデータバインドかそうでない場合は、上記の二つの方法にかかわらず動作するはずです。お役に立てれば。

関連する問題