2012-03-07 45 views
15

DataGridViewのComboBoxColumnをセットアップし、選択可能な値を列挙から設定しました。ほとんどの場合、次の例外を除いて私が望むように動作します。DataGridView ComboBox Column:ドロップダウンから選択した後にセル値を変更しますか?

ドロップダウン矢印をクリックして列挙値の1つを選択するたびに、CellValueChangedイベントがトリガーされない「中間」状態のソートにとどまります。私はイベントが発砲するために別の細胞や別のコントロールに集中する必要があります。

また、セルが空でないことを確認して内容を「検証」する、DataGridViewのLeavingイベントのイベントハンドラもあります。

したがって、行を作成してすべてのセルを塗りつぶして(現在は空白の)ComboBox列に移動した場合は、値に変更してから「実行」ボタンをクリックします。 ComboBoxの選択が「保存」されていないため、エラーダイアログが表示されます。

どうすればこの問題を回避できますか?ドロップダウンから値を選択した後、自動的に値を「設定」する方法はありますか?

ありがとうございます!

答えて

19

あなたはCurrentCellDirtyStateChangedイベントを使用してグリッドに編集をコミットを強制する必要があります。

private void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e) 
    { 
     dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit); 
    } 

はそれが役に立てば幸い!

+0

最も確かにしました!ありがとう! – john

3

を強制的に実行する前に、DataGridViewColumnDataGridViewComboBoxColumnのタイプであるかどうかをチェックして、イオンデンの答えを拡張します。これにより、他のDataGridViewColumnオブジェクトのコミットが早すぎるのを防ぐことができます。フォーカスが完全に行を残しているまで

dataGridView1.CurrentCellDirtyStateChanged += dataGridView1_CurrentCellDirtyStateChanged; 

    void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e) 
    { 
     DataGridViewColumn col = dataGridView1.Columns[dataGridView1.CurrentCell.ColumnIndex]; 
     if (col is DataGridViewComboBoxColumn) 
     { 
      dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit); 
     } 
    } 
0

は、ここで私はいくつかのケースでは問題

Private Sub dgvEcheancier_CurrentCellDirtyStateChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles dgvEcheancier.CurrentCellDirtyStateChanged 
     nbreClick += 1 
      With dgvEcheancier 
       Select Case .CurrentCell.ColumnIndex 
       Case 9 
        Dim col As DataGridViewComboBoxColumn = .Columns(9) 
        If TypeOf (col) Is DataGridViewComboBoxColumn Then 
         dgvEcheancier.CommitEdit(DataGridViewDataErrorContexts.Commit) 
         If nbreClick = 2 Then 
          MessageBox.Show("y" & "val=" & .CurrentCell.Value) 
          nbreClick = 0 
         End If 
        End If 

      End Select 
      End With 
+0

c#タグを見てください。 –

1

を解く方法です、値がくっつきません。その場合には、最後に現在の編集を強制する唯一の方法は、全体のバインディングコンテキストでそれを終了することです:

mGridView.CommitEdit(DataGridViewDataErrorContexts.Commit); 
mGridView.BindingContext[mGridView.DataSource].EndCurrentEdit(); // <<=== 

私はこのヒントhereを見つけました。

11

私は、Moopの答えを列の種類ではなくセルの種類を調べることで拡張します。

dataGridView1.CurrentCellDirtyStateChanged += dataGridView1_CurrentCellDirtyStateChanged; 

void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e) 
{ 
    if (CurrentCell is DataGridViewComboBoxCell) 
    { 
     dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit); 
     dataGridView1.EndEdit(); 
    } 
} 
0
void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e) 
{ 
    dataGridView1.BeginEdit(true); 
    ComboBox cmbMiCtrl=(ComboBox)dataGridView1.EditingControl; 
    string Valor= cmbMiCtrl.Text; 
    dataGridView1.EndEdit(); 
} 
0

一つ私が見た問題:あなたが選択した場合、それは動作しません。 GridView.EditMode = System.Windows.Forms.DataGridViewEditMode.EditOnEnter;

0

私は、セルの値がないことに気づかなかったので、私はエラーを探して2時間のように過ごしますデフォーカスしていないと保存されません。コンボボックスが保存中に白濁しているため、セルがデフォーカスしていないことに気づいただけです(btnイベント)。 それだけでなく、EditOnEnter-Modeは上記の他のほとんどのメソッドが動作することを前提としています。 EditOnEnterを使用する理由は、DataGridViewComboBoxColumnを使用する場合、EditModeをEditOnEnterに設定しないとドロップダウンを開くために2回クリックする必要があるためです。

this.dataGridView.EditMode = DataGridViewEditMode.EditOnKeystrokeOrF2; this.dataGridView.EndEdit(); this.dataGridView.EditMode = DataGridViewEditMode.EditOnEnter;

私はこのことができます願っています。なぜオブジェクトの値がGUIに表示されていないのかと疑問に思ったのは約2時間でした。

0

私はすでに起こった議論のフォローアップとして私の答えを加えています。私は行ごとに異なるコンボボックスを持つDataGridViewを構築しようとしていました。彼らはまた、ワンクリックに反応しなければならなかった。そして、選択が行われたとき、行内の別のセルをコンボボックスの選択に従って変更する必要がありました。変更は、選択が行われるとすぐに発生する必要がありました。私の主な問題は、OPのように、コンボボックスがフォーカスを失うまでは起こらないということでした。

このようなDataGridViewの完全な動作の最小例がここにあります。私はそれを最小限に抑える必要がありました。なぜなら、私のすべての要件を同時に働かせるのは難しいからです。いくつかのSOの投稿がこれに入りました。後ほど参考文献を投稿します。しかし、今のところ、ここに...行く

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Windows.Forms; 

namespace TestDGV 
{ 
public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private Panel panel2; 
    private DataGridView TestGrid; 

    private void InitializeComponent() 
    { 
     this.panel2 = new System.Windows.Forms.Panel(); 
     this.SuspendLayout(); 
     // 
     // panel2 
     // 
     this.panel2.Dock = DockStyle.Fill; 
     this.panel2.Name = "panel2"; 
     this.panel2.TabIndex = 1; 
     // 
     // Form1 
     // 
     this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 
     this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 
     this.ClientSize = new System.Drawing.Size(661, 407); 
     this.Controls.Add(this.panel2); 
     this.Name = "Form1"; 
     this.Text = "Form1"; 
     this.Load += new System.EventHandler(this.Form1_Load); 
     this.ResumeLayout(false); 
    } 

    private void Form1_Load(object sender, EventArgs e) 
    { 
     //basic grid properties 
     TestGrid = new DataGridView(); 
     TestGrid.Dock = DockStyle.Fill; 
     TestGrid.AutoGenerateColumns = false; 
     TestGrid.Name = "TestGrid"; 
     TestGrid.ReadOnly = false; 
     TestGrid.EditMode = DataGridViewEditMode.EditOnEnter; 

     //Event handlers 
     TestGrid.DataBindingComplete += TestGrid_DataBindingComplete; 
     TestGrid.CurrentCellDirtyStateChanged += TestGrid_CurrentCellDirtyStateChanged; 
     TestGrid.CellValueChanged += TestGrid_CellValueChanged; 

     //columns 
     var textCol = new DataGridViewTextBoxColumn(); 
     textCol.HeaderText = "Text"; 
     textCol.Name = "Text"; 
     textCol.DataPropertyName = "Text"; 
     textCol.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; 
     TestGrid.Columns.Add(textCol); 

     var comboCol = new DataGridViewComboBoxColumn(); 
     comboCol.HeaderText = "ComboBox"; 
     comboCol.Name = "ComboBox"; 
     comboCol.AutoComplete = true; 
     comboCol.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; 
     TestGrid.Columns.Add(comboCol); 

     var resultCol = new DataGridViewTextBoxColumn(); 
     resultCol.HeaderText = "Result"; 
     resultCol.Name = "Result"; 
     resultCol.DataPropertyName = "Result"; 
     resultCol.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; 
     TestGrid.Columns.Add(resultCol); 

     //Bind the data 
     Datum.TestLoad(); 
     TestGrid.DataSource = Datum.Data; 

     panel2.Controls.Add(TestGrid); 
    } 

    void TestGrid_CellValueChanged(object sender, DataGridViewCellEventArgs e) 
    { 
     if (e.RowIndex < 0 || e.ColumnIndex < 0) 
      return; 

     var row = TestGrid.Rows[e.RowIndex]; 
     var cell = row.Cells[e.ColumnIndex]; 
     if (cell is DataGridViewComboBoxCell) 
     { 
      var val = cell.Value as string; 
      var datum = row.DataBoundItem as Datum; 
      datum.Current = val; 
      row.Cells["Result"].Value = datum.Result; 
      TestGrid.InvalidateRow(e.RowIndex); 
     } 
    } 


    void TestGrid_CurrentCellDirtyStateChanged(object sender, EventArgs e) 
    { 
     if(TestGrid.CurrentCell is DataGridViewComboBoxCell) 
     { 
      TestGrid.CommitEdit(DataGridViewDataErrorContexts.Commit); 
      TestGrid.EndEdit(); 
     } 
    } 

    void TestGrid_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e) 
    { 
     foreach (DataGridViewRow row in TestGrid.Rows) 
     { 
      var datum = row.DataBoundItem as Datum; 
      if (datum == null) 
       return; 

      var cell = row.Cells["ComboBox"] as DataGridViewComboBoxCell; 
      if (cell.DataSource == null) 
      { 
       cell.DisplayMember = "KeyDisplayValue"; 
       cell.ValueMember = "KeyValue"; 
       cell.DataSource = (row.DataBoundItem as Datum).Combo; 
       cell.Value = (row.DataBoundItem as Datum).Current; 
      } 
     } 
     TestGrid.DataBindingComplete -= TestGrid_DataBindingComplete; 
    } 

    public class Datum 
    { 
     public static void TestLoad() 
     { 
      var t1 = new Triplet[] { 
        new Triplet("1", "World", "Everyone"), 
        new Triplet("2", "Charlie", "Friend of Algernon"), 
        new Triplet("3", "Lester", "Phenomenal programmer"), 
      }; 
      var t2 = new Triplet[] { 
        new Triplet("1", "World", "Everyone"), 
        new Triplet("4", "Mary", "Wife of George Bailey"), 
        new Triplet("3", "Lester", "Phenomenal programmer"), 
      }; 
      Data.Add(new Datum("hello, ", t1.ToList())); 
      Data.Add(new Datum("g'bye, ", t2.ToList())); 
     } 
     public static List<Datum> Data = new List<Datum>(); 

     public Datum(string text, List<Triplet> combo) 
     { 
      this._text = text; 
      this._combo = combo.ToDictionary<Triplet,string>(o => o.KeyValue); 
      this.Current = combo[0].KeyValue; 
     } 

     private string _text; 
     public string Text 
     { 
      get 
      { 
       return _text; 
      } 
     } 

     private Dictionary<string, Triplet> _combo; 
     public List<Triplet> Combo 
     { 
      get 
      { 
       return _combo.Values.ToList(); 
      } 
     } 

     private string _result; 
     public string Result 
     { 
      get 
      { 
       return _result; 
      } 
     } 

     private string _current; 
     public string Current 
     { 
      get 
      { 
       return _current; 
      } 
      set 
      { 
       if (value != null && _combo.ContainsKey(value)) 
       { 
        _current = value; 
        _result = _combo[value].Description; 
       } 
      } 
     } 
    } 

    public class Triplet 
    { 
     public string KeyValue { get; set; } 
     public string KeyDisplayValue { get; set; } 
     public string Description { get; set; } 
     public Triplet(string keyValue, string keyDisplayValue, string description) 
     { 
      KeyValue = keyValue; 
      KeyDisplayValue = keyDisplayValue; 
      Description = description; 
     } 
    } 
} 
} 
0

あなたはグリッド上で変更イベントを起動し、イベント内で変更をコミットする必要があり、それが選択された後にアイテムを保存するために、コントロールを残すCellValueChangedを使用する必要があります。

private void FilterdataGrid_CellValueChanged(object sender, DataGridViewCellEventArgs e) 
{ 
    FilterdataGrid.CommitEdit(DataGridViewDataErrorContexts.Commit);  

    FilterdataGrid.EndEdit(DataGridViewDataErrorContexts.LeaveControl); 
} 

希望します。

+2

将来のユーザーが恩恵を受けられるように、いくつかのコンテキストと説明を回答に追加してください。プレーンコードによる応答は、将来のユーザーにとってより一般的な回答となる可能性は非常に低いです。詳細については[回答]を見てください。 –

0

EndCurrentEditについてのDrojのおかげで、私はそれを私のために働かせる必要がありました。 これは私がすぐにDataGridViewComboBoxColumnsとDataGridViewCheckBoxColumnsをコミットするためにやってしまったものです:

private void dataGridViewEnumerable_CurrentCellDirtyStateChanged(object sender, EventArgs e) 
{ 
    var dataGridView = sender as DataGridView; 
    if (dataGridView == null || dataGridView.CurrentCell == null) 
    return; 
    var isComboBox = dataGridView.CurrentCell is DataGridViewComboBoxCell; 
    if ((isComboBox || dataGridView.CurrentCell is DataGridViewCheckBoxCell) 
    && dataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit) 
    && isComboBox && dataGridView.EndEdit()) 
    dataGridView.BindingContext[dataGridView.DataSource].EndCurrentEdit(); 
} 
2

この問題のCurrentCellDirtyStateChangedイベントの固定マウスの相互作用が、それはキーボード操作を破る - 、そして、アップ/ダウン矢印すべての矢印をクリックし結果F4を使用してダーティな状態で変更し、編集をコミットします。私が見つけた解決策は、作成時に "DataGridViewComboBoxEditingControl"を取得し、DropDownClosedイベントをそれに添付することでした。これは、キーボードとマウスのやりとりに有効です。この例では、DataGridViewを拡張して、すべてのインスタンスがこの機能を継承するようにしました。

protected override void OnEditingControlShowing(DataGridViewEditingControlShowingEventArgs e) 
    { 
     DataGridViewComboBoxEditingControl control = e.Control as DataGridViewComboBoxEditingControl; 
     if (control != null) 
     { 
      control.DropDownClosed -= ComboBoxDropDownClosedEvent; 
      control.DropDownClosed += ComboBoxDropDownClosedEvent; 
     } 
     base.OnEditingControlShowing(e); 
    } 

    void ComboBoxDropDownClosedEvent(object sender, EventArgs e) 
    { 
     DataGridViewComboBoxCell cell = CurrentCell as DataGridViewComboBoxCell; 
     if ((cell != null) && cell.IsInEditMode) 
     { 
      CommitEdit(DataGridViewDataErrorContexts.Commit); 
      EndEdit(); 
     } 
    } 
関連する問題