5

いくつかのDataGridViewComboBoxColumnsを持つDataGridViewがあります。コンボボックスのシングルクリックドロップダウンを目的として、DataGridViewにCellEnterイベントハンドラーがあります。

列はKeyValuePairsのリストにバインドされ、ValueMemberは「Key」、DisplayMemberは「Value」です。

コンボボックスの列をクリックすると、正常に機能します。ただし、セルが「ドロップダウン」状態にあり、別のコンボボックス(同じ列、別の行)をクリックすると、古いセルの選択が適切に解除され、新しいセルが選択されてドロップダウンされますが、上部の選択された値はに変わります。正しいセルに戻す前に、古いセルから一瞬の値。

たとえば、リストがA、B、Cであるとします。行1でAが選択され、行2でBが選択されます。行1のセルをクリックすると、すべてが正常になります。次に、このセルをドロップダウンしながら、row2のセルをクリックします。正しくドロップダウンしますが、一番上で選択した値がAになり、すぐにB(正しい値)に戻ります。

2番目のコンボボックスセルをクリックする前に他の列のセルをクリックしても、これは発生しません。

これを防ぐ方法はありますか?

問題を再現するためのサンプルコード(イベントハンドラーは明らかなイベントに接続されています):

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace PDGV
{
    public partial class Form1 : Form
    {
        List<KeyValuePair<string, string>> bindingList = new List<KeyValuePair<string, string>>();

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            dataGridView1.Rows.Add(10);
            bindingList.Add(new KeyValuePair<string,string>("aaa", "111"));
            bindingList.Add(new KeyValuePair<string,string>("bbb", "222"));
            bindingList.Add(new KeyValuePair<string,string>("ccc", "333"));
            bindingList.Add(new KeyValuePair<string,string>("ddd", "444"));
            bindingList.Add(new KeyValuePair<string,string>("eee", "555"));
            BindComboList(2, bindingList);

        }

        private void BindComboList(int columnIndex, object list)
        {
            var column = dataGridView1.Columns[columnIndex] as DataGridViewComboBoxColumn;
            if (column != null)
            {
                column.DataSource = new BindingSource(list, null);
                column.DisplayMember = "Value";
                column.ValueMember = "Key";
            }
        }

        private void dataGridView1_CellEnter(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex == -1)
                return;

            dataGridView1.BeginEdit(true);
            var control = dataGridView1.EditingControl as DataGridViewComboBoxEditingControl;
            if (control != null)
                control.DroppedDown = true;
        }
    }
}
4

3 に答える 3

4

キューズ:

のEndEditメソッドの奥深くDataGridViewに、以前に使用されたEditingControlのコピーが格納されます。this.latestEditingControl = this.editingControl; 次に、別のセルの編集を開始すると、キックインしますBeginEditInternal。この間、latestEditingControlがnullでなく、編集タイプが最後のセルと同じであるかどうかをチェックします。そうである場合は、コントロールを再利用します。これがフラッシュが表示される理由であり、実際には同じコントロールです。

ソリューション:

latestEditingControlをnullに設定します。このコントロールには、通常のプロパティ/メソッドからアクセスできません。リフレクションを使用する必要があります。注:これにより、まったく異なる煩わしさが生じます。これで、残しているセルが白く点滅します:)が、助けを求めた特定の問題は解決されます。

    private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
    {
        if (e.RowIndex == -1)
            return;

        //this.latestEditingControl
        Type t = dataGridView1.GetType();
        FieldInfo viewSetter = t.GetField("latestEditingControl", BindingFlags.Default | BindingFlags.NonPublic | BindingFlags.Instance);
        viewSetter.SetValue(dataGridView1, null);
    }
于 2012-07-17T23:01:49.880 に答える
2

説明したように問題を100%再現しませんでした(ラグは見られませんでした)が、CellEnterイベントのサブスクライブを解除して、コードをこれに変更してみてください(DataGridViewコンボボックスにドロップダウンリストをワンクリックで表示するにはどうすればよいですか?)。

public Form1() {
  InitializeComponent();

  dataGridView1.EditMode = DataGridViewEditMode.EditOnEnter;
  dataGridView1.EditingControlShowing += dataGridView1_EditingControlShowing;
}

void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) {
  if (e.Control is ComboBox) {
    SendKeys.Send("{F4}");
  }
}

ユーザーがセルに入ると、ComboBoxがポップオープンするはずです。


またはこのソリューションからシングルクリックで(データグリッドビューで)ドロップダウンを開きます

void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) {
  if (e.Control is ComboBox) {
    ComboBox ctl = e.Control as ComboBox;
    ctl.Enter -= new EventHandler(ctl_Enter);
    ctl.Enter += new EventHandler(ctl_Enter);
  }
}

void ctl_Enter(object sender, EventArgs e) {
  (sender as ComboBox).DroppedDown = true;
}
于 2012-07-16T18:58:45.530 に答える
1

私はそれをWindows7の3Dスタイルのコンボボックスであると思います(多分ビスタも、私はチェックしていません)

あなたがいたらこれが起こるのを見たことがない

comboboxcolumn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;

しかし、あなたはそれがどのように見えるか気に入らないかもしれません。あなたは醜い平らな下向き矢印を隠すことができます

comboboxcolumn.DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing;

他の人が言ったように、列ごとに1つのコンボボックスコントロール(「編集コントロール」)があり、その同じコンボボックスがその列の現在アクティブなセルに表示されます。セルが選択されていない場合、ユーザーが表示できるように偽のコンボボックスをペイントするのは、列クラスの描画メソッド次第です。したがって、値を非表示のコンボボックスにプッシュしてから別の場所に再描画すると発生する、特定の3Dポップアップスタイルの内部コンボ描画の問題である可能性があります。

「クラシック」ウィンドウテーマに切り替えてみてください。その場合、コンボボックスはそれ自体で動作するはずです。Aeroにいる間に、コンボボックスにクラシックテーマでのレンダリングと同じようにレンダリングさせることができれば興味深いでしょう。可能かどうかはわかりませんが、調べてみてください。

しかしとにかく、dgvが他のコンボボックススタイルでこの問題を抱えていないという事実は、その新しいコンボボックススタイルがdatagridviewにうまく適合していないと私に思わせます。

于 2012-07-18T07:22:55.793 に答える