2017-03-12 35 views
1

私は最終的に私のために動作するカスタムNumericUpDownCellを発見しました。 (リンク:custom NumericUpDownCell、Loathingによって作成されました。)すべてが順調です。C#DataGridView - セル値の検出変更

しかし、新しい問題が発生します:購入する商品の量を増やすために上向きの矢印を使用した場合、別の列(価格セル)の価値をすぐに上げたい)。 amount-cell-valueが変更されたときに反応するリスナーを作成するにはどうすればよいですか?

DataGridViewでCellValueChangedイベントを使用しようとしました。しかし、それは奇妙に反応しました。最初にアプリケーションを開始しました(DataGridViewが作成され、それに反応したと思います)。次に、値を増やしていたセルの選択を解除した後、最初に反応しました。

上矢印をクリックするとすぐに反応します。私は、Loathingのコードをリスナーを追加するためにmodに変更する方法があると考えましたか?しかし、私は自分でそれを行うのに十分な能力がありません。私がまだ見つけていない組み込みの方法がないかぎり?

+0

いただきました!あなたはそれのために使う現在のコード?あなたが提供したリンク自体が質問です。その質問に与えられた答えを正確に使用していますか? –

+0

はい、私はリンクの質問に対する答えのコードを使用しています。 (Loathingによって作成されました。) –

+0

We.needコードは、何も表示せずにデバッグしようとして無駄です –

答えて

0

簡単な解決策は、DataGridViewののEditingControlShowingイベントを使用して、コードを以下のようにEditingControlValueChangedイベントのイベントハンドラを登録することです:

NumericUpDownEditingControl lastCtl = null; 
EventHandler handler = null; 

private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) 
{ 
    var ctl = e.Control as NumericUpDownEditingControl; 
    if (ctl != null) //&& ctl != lastCtl 
    { 
     if (handler == null) handler = new EventHandler(myUpDownCtl_ValueChanged); //save a handler has better performance 
     //Event => ValueChanged: just fires for Up/Dn btn or when press enter, TextChanged: also fired during user typing 
     if (lastCtl != null) lastCtl.ValueChanged -= handler; //ensure we remove our handler. 
     lastCtl = ctl; 
     lastCtl.ValueChanged += handler; //we can use myUpDownCtl_ValueChanged directly instead of that handler var 
     //handler(sender, EventArgs.Empty); 
    } 
} 

void myUpDownCtl_ValueChanged(object sender, EventArgs e) 
{ 
    MessageBox.Show("New value: " + lastCtl.Value.ToString()); 
    //Grid1.CurrentRow.Cells[5].Value = lastCtl.Value * 10; //sample to change other columns based on this value 
} 

注:のみアップ/ダウンボタンのValueChangedイベントが発生しますかユーザーが数字を入力してEnterキーを押します。ユーザーがNumeric TextBox内に入力している間にも更新したい場合は、代わりにTextChangedを使用してください。

また、InitializeEditingControl方法についての嫌がらせによって提供されたその回答に投稿されたコメントにも注意してください。

更新:

これでテストの全コード:

public partial class Form4 : Form 
{ 
    public Form4() 
    { 
     InitializeComponent(); 
    } 

    private void Form4_Load(object sender, EventArgs e) 
    { 
    } 

    NumericUpDownEditingControl lastCtl = null; 
    EventHandler handler = null; 

    private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) 
    { 
     var ctl = e.Control as NumericUpDownEditingControl; 
     if (ctl != null) //&& ctl != lastCtl 
     { 
      if (handler == null) handler = new EventHandler(myUpDownCtl_ValueChanged); //save a handler has better performance 
      //Event => ValueChanged: just fires for Up/Dn btn or when press enter, TextChanged: also fired during user typing 
      if (lastCtl != null) lastCtl.ValueChanged -= handler; //ensure we remove our handler. 
      lastCtl = ctl; 
      lastCtl.ValueChanged += handler; //we can use myUpDownCtl_ValueChanged directly instead of that handler var 
      //handler(sender, EventArgs.Empty); 
     } 
    } 

    void myUpDownCtl_ValueChanged(object sender, EventArgs e) 
    { 
     //MessageBox.Show("New value: " + lastCtl.Value.ToString()); 
     dataGridView1.CurrentRow.Cells[1].Value = lastCtl.Value * 10; //sample to change other columns based on this value 
    } 

} //end Form 


//**************************************************************** 


public class NumericUpDownColumn : DataGridViewColumn { 

    public NumericUpDownColumn() : base(new NumericUpDownCell()) { 
     this.ValueType = typeof(decimal?); 
    } 

    public override DataGridViewCell CellTemplate { 
     get { 
      return base.CellTemplate; 
     } 
     set { 
      if (!(value is NumericUpDownCell)) 
       throw new InvalidCastException("Must be a NumericUpDownCell"); 

      base.CellTemplate = value; 
     } 
    } 
} 

public class NumericUpDownCell : DataGridViewTextBoxCell { 

    public override void InitializeEditingControl(int rowIndex, Object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle) { 
     // required to initialize the editing control: 
     base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle); 
     var ctl = (NumericUpDownEditingControl) DataGridView.EditingControl; 
     //NumericUpDownColumn cc = (NumericUpDownColumn) this.OwningColumn; 
     if (this.Value == null || this.Value == DBNull.Value) { 
      ctl.Value = (ctl.Minimum <= 0 && ctl.Maximum >= 0 ? 0 : ctl.Minimum); 
     } 
     else { 
      Object trueValue = this.Value; 
      ctl.Value = Convert.ToDecimal(trueValue); //(decimal)trueValue; 
     } 
    } 

    public override Type EditType { 
     get { 
      return typeof(NumericUpDownEditingControl); 
     } 
    } 

    public override Type ValueType { 
     get { 
      return base.ValueType; 
     } 
     set { 
      base.ValueType = value; 
     } 
    } 

    public override Object DefaultNewRowValue { 
     get { 
      return DBNull.Value; 
     } 
    } 
} 

[ToolboxItem(false)] //don't show this as a new control in toolbox 
public class NumericUpDownEditingControl : NumericUpDown, IDataGridViewEditingControl { 

    private bool Cancelling = false; 

    public NumericUpDownEditingControl() { 
    } 

    // Implements the IDataGridViewEditingControl.EditingControlFormattedValue property. 
    public Object EditingControlFormattedValue { 
     get { 
      // must return a String 
      // it doesn't matter if the value is formatted, it will be replaced 
      // by the formatting events 
      String s = "" + this.Value.ToString(); 
      return s; 
     } 

     set { 
      decimal val = 0; 
      if (value is decimal) 
       this.Value = (decimal) value; 
      else { 
       String s = "" + value; 
       if (s.Length > 0) { 
        if (decimal.TryParse(s, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.CurrentCulture, out val)) 
         this.Value = val; 
       } 
      } 
     } 
    } 

    protected override void OnLeave(EventArgs e) { 
     if (!Cancelling) { 
      var dgv = this.EditingControlDataGridView; 
      var cell = (NumericUpDownCell) dgv.CurrentCell; 
      cell.Value = this.Value; 
     } 

     base.OnLeave(e); 
     Cancelling = false; 
    } 


    protected override void OnKeyDown(KeyEventArgs e) { 
     if (e.KeyCode == Keys.Escape) { 
      Cancelling = true; 
      e.Handled = true; 
      e.SuppressKeyPress = true; 
      var dgv = this.EditingControlDataGridView; 
      dgv.CancelEdit(); 
      dgv.EndEdit(); 
     } 

     base.OnKeyDown(e); 
    } 

    // Implements the IDataGridViewEditingControl.GetEditingControlFormattedValue method. 
    public Object GetEditingControlFormattedValue(DataGridViewDataErrorContexts context) { 
     return EditingControlFormattedValue; 
    } 

    // Implements the IDataGridViewEditingControl.ApplyCellStyleToEditingControl method. 
    public void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle) { 
     this.Font = dataGridViewCellStyle.Font; 
     this.ForeColor = dataGridViewCellStyle.ForeColor; 
     this.BackColor = dataGridViewCellStyle.BackColor; 
    } 

    // Implements the IDataGridViewEditingControl.EditingControlRowIndex property. 
    public int EditingControlRowIndex { get; set; } 

    // Implements the IDataGridViewEditingControl.EditingControlWantsInputKey method. 
    public bool EditingControlWantsInputKey(Keys key, bool dataGridViewWantsInputKey) { 
     switch (key & Keys.KeyCode) { 
      case Keys.Left: 
      case Keys.Up: 
      case Keys.Down: 
      case Keys.Right: 
      case Keys.Home: 
      case Keys.End: 
      case Keys.PageDown: 
      case Keys.PageUp: 
      case Keys.Escape: 
       return true; 
      default: 
       return !dataGridViewWantsInputKey; 
     } 
    } 

    // Implements the IDataGridViewEditingControl.PrepareEditingControlForEdit method. 
    public void PrepareEditingControlForEdit(bool selectAll) { 
     // No preparation needs to be done. 
    } 

    // Implements the IDataGridViewEditingControl.RepositionEditingControlOnValueChange property. 
    public bool RepositionEditingControlOnValueChange { 
     get { 
      return false; 
     } 
    } 

    // Implements the IDataGridViewEditingControl.EditingControlDataGridView property. 
    public DataGridView EditingControlDataGridView { get; set; } 

    // Implements the IDataGridViewEditingControl.EditingControlValueChanged property. 
    public bool EditingControlValueChanged { get; set; } 

    // Implements the IDataGridViewEditingControl.EditingPanelCursor property. 
    public Cursor EditingPanelCursor { 
     get { 
      return base.Cursor; 
     } 
    } 
} 
+0

これは私が必要としていたものです。ありがとうございました。 =) –

+0

実際に新しい問題が発生しました。私はコードを追加し、データテーブルで少し遊んでいました。 1つの行を選択し、その値を増減することは魅力的です。しかし、行1を選択して値を変更し、行2を選択して値を変更しようとすると、アプリケーションがクラッシュします。私に 'NullReferenceException'を与えます。この例外を抑制するために、コードにtry/catchを追加する方法はありますか? –

+0

私はそれをテストし、それはうまく動作します、あなたはあなたの完全なコードをここに与えることができますか? –

関連する問題