2

DataGridViewComboBoxColumnバインドされた値で満たされている場合、プロパティを設定するとDisplayMember、次のDataErrorイベントが発生しますFormatException

DataGridViewComboBoxCell の値が無効です

DisplayMemberが設定されておらず、ビューに の結果が表示されている場合、.ToString()すべてが期待どおりに機能します。

完全な例を次に示します。

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

    private void Form1_Load(object sender, EventArgs e)
    {
        var categories = new[] { CustomerCategory.Cat1, CustomerCategory.Cat2, CustomerCategory.Cat3 };
        this.dataGridView1.AutoGenerateColumns = false;
        this.dataGridView1.DataError += new DataGridViewDataErrorEventHandler(dataGridView1_DataError);
        this.dataGridView1.CellParsing += new DataGridViewCellParsingEventHandler(dataGridView1_CellParsing);
        this.dataGridView1.Columns.Add(new DataGridViewComboBoxColumn()
        {
            DataSource = categories,
            HeaderText = "Category",
            DataPropertyName = "Category",
            DisplayMember = "Name" // if we omit this line, there is not DataError event raised
        });

        this.dataGridView1.DataSource = new[] 
        { 
              new Customer() { Category = CustomerCategory.Cat1 } 
            , new Customer() { Category = CustomerCategory.Cat2 } 
            , new Customer() { Category = CustomerCategory.Cat3 } 
        }.ToList();
    }

    void dataGridView1_DataError(object sender, DataGridViewDataErrorEventArgs e)
    {
        var value = this.dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
        var type = value != null ? value.GetType() : null;
        string message = "Error"
            + Environment.NewLine + " - Column : " + e.ColumnIndex
            + Environment.NewLine + " - Line  : " + e.RowIndex
            + Environment.NewLine + " - Value : " + Convert.ToString(value) + " (" + type + ")"
            + Environment.NewLine + " - Exception : " + e.Exception.Message;
        Debug.Fail(message);
    }

    void dataGridView1_CellParsing(object sender, DataGridViewCellParsingEventArgs e)
    {
        //http://stackoverflow.com/questions/631126/how-to-bound-a-datagridviewcomboboxcolumn-to-a-object
        if (this.dataGridView1.CurrentCell.OwningColumn is DataGridViewComboBoxColumn)
        {
            var editingControl = (DataGridViewComboBoxEditingControl)this.dataGridView1.EditingControl;
            e.Value = editingControl.SelectedItem;
            e.ParsingApplied = true;
        }
    }
}

モデル:

public class CustomerCategory
{
    public static readonly CustomerCategory Cat1 = new CustomerCategory { Name = "Cat1" };
    public static readonly CustomerCategory Cat2 = new CustomerCategory { Name = "Cat2" };
    public static readonly CustomerCategory Cat3 = new CustomerCategory { Name = "Cat3" };

    public string Name { get; set; }
    public override string ToString() { return this.Name; }
}
public class Customer { public CustomerCategory Category { get; set; } }

DisplayMemberこの迷惑なDataErrorイベントを発生させることなく、どうすれば自分自身を指定できますか?
この問題は でのみ発生DataGridViewComboBoxColumnし、通常の では発生しませんComboBox

編集:いくつかのテストの後、私はそれを言うことができます:

[DisplayMember + Not ValueMember] = FAIL
[Not DisplayMember + ValueMember] = FAIL
[DisplayMember + ValueMember] = WIN

したがって、私の質問は次のように言い換えることができます。何が機能し、何が機能しないかを正確に説明するドキュメントはありますか。そして、どのようにDisplayMember+ValueMemberがリンクされているように見えますか?

再編集:

興味深いリファレンス: DataGridViewComboBoxColumn の問題

ただし、DataGridViewComboBoxColumn はこのようには機能しません。DisplayMember を設定しないと ToString 値が表示されますが、SelectedItem を検索しようとすると内部的に問題が発生するため、DisplayMember をパブリック プロパティに設定する必要があります。あなたのクラス。さらに悪いことに、ValueMember プロパティを設定しない場合のデフォルトの動作は DisplayMember を返すことであり、実際のアイテム自体を取得する方法はありません。唯一の回避策は、自身を返すプロパティをクラスに追加し、そのプロパティを ValueMember に設定することです。もちろん、項目が変更できないもの (フレームワーク クラスの 1 つなど) である場合は、項目への参照を保持するコンテナー オブジェクトをまとめる必要があります。

内部で何かがうまくいかないという情報を誰かが持っていますか?

4

1 に答える 1