Search code examples
c#winforms

Does the order of assigning DataSource to BindingSource and assigning DisplayMember to ComboBox in WinFoms matter?


I found that the following two codes reversing the order of assigning DataSource to the BindingSource and assigning DisplayMember to my ComboBox actually give different results. When I assign the DisplayMember before defining the DataSource like the following codes, the ComboBox actually fails to display my desired DisplayMember (myProtocolInstance.Name), but output "myNameSpace.Protocol". The two messagebox both show a empty string.

Dictionary<string, BindingSource> bs = new Dictionary<string, BindingSource>() {"protocol", new BindingSource()};
this.protocolCombo.DataSource = bs["protocol"];
MessageBox.Show($"{this.protocolCombo.DisplayMember}");  //output: ""
this.protocolCombo.DisplayMember = "Name";
MessageBox.Show($"{this.protocolCombo.DisplayMember}");  //output: ""
bs["protocol"].DataSource = protocol_list;

However when I reverse their orders like this, then the ComboBox correctly shows my desired Name properties from the Protocol instance. And the Messagebox also show more reasonable output, with the first one showing empty string and the second one showing "Name".

Dictionary<string, BindingSource> bs = new Dictionary<string, BindingSource>() {"protocol", new BindingSource()};
this.protocolCombo.DataSource = bs["protocol"];
MessageBox.Show($"{this.protocolCombo.DisplayMember}");  //output: ""
bs["protocol"].DataSource = protocol_list;
this.protocolCombo.DisplayMember = "Name";
MessageBox.Show($"{this.protocolCombo.DisplayMember}");  //output: "Name"

Simiplified version of Protocol class

public class Protocol
{
    public string Name {  get; set; }
    public Protocol(string name) 
    {
        Name = name;
    }
}

I wonder if this is a defect in Winform or it is designed in this way?

Supplementary information: This project is written under .Net6.0


Solution

  • Thank all who has answered my question, particularly @Jimi who has given very detailed explaination on the mechanism of DisplayMember and DataSource. For those who come across this post looking for answers of similar question, this is how I finially settle:

    Dictionary<string, BindingSource> bs = new Dictionary<string, BindingSource>() {"protocol", new BindingSource()};
    this.protocolCombo.DisplayMember = "Name";
    this.protocolCombo.ValueMember = "Name";
    bs["protocol"].DataSource = new Protocol();
    this.protocolCombo.DataSource = bs["protocol"];
    

    I created dummy instances of my various Types (One of them = Class Protocol in this codes) with parameterless constructors to initialize all BindingSource before mounting them to my control elements. Although the document of BS.DataSource mentions that a non-list Type can be assigned to the DataSource to create a Empty IBindingList of type "T" (which I think is more reasonble than creating a dummy instance and let the GC handle it after the initialization?), I can't make it work as VS warns me of "'Protocol' is a 'Type', which is not valid in the given context." I still appreciate it if anyone can tell me whether this is an acceptable practice and why assigning a non-list Type doesn't work as stated in the document. But anyway, this is how I settle the problem. Thank you all.