Unable to set the ValueMember of a ComboBox to a non Browsable property

E

eratchev

Setting the ValueMember property of a ComboBox to a name of a property
that is not browsable throws the following exception.

System.ArgumentException: Could not bind to the new display member.
Parameter name: newDisplayMember

It works fine if I set Browsable to true.
Has anyone encountered this before? Seems like a bug to me.

This is how I set up the DataSource:

ArrayList list = new ArrayList();
list.Add(new Person("John Doe"));
this.comboBox.DataSource = list;
this.comboBox.DisplayMember = "Name";
this.comboBox.ValueMember = "Name";

This is my Person class:

public class Person
{
string _name;
public Person(string name)
{
this._name = name;
}

[Browsable(false)]
public string Name
{
get { return this._name; }
set { this._name = value; }
}
}



Here is the complete code listing:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace BrowsableAttributeTest
{
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.ComboBox comboBox;
private System.ComponentModel.Container components = null;

public Form1()
{
InitializeComponent();

ArrayList list = new ArrayList();
list.Add(new Person("John Doe"));
this.comboBox.DataSource = list;
this.comboBox.DisplayMember = "Name";
try
{
this.comboBox.ValueMember = "Name";
}
catch(Exception e)
{
MessageBox.Show(e.ToString(), e.GetType().ToString());
}
}

protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.comboBox = new System.Windows.Forms.ComboBox();
this.SuspendLayout();
//
// comboBox
//
this.comboBox.DropDownStyle =
System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBox.Location = new System.Drawing.Point(24, 32);
this.comboBox.Name = "comboBox";
this.comboBox.Size = new System.Drawing.Size(184, 21);
this.comboBox.TabIndex = 0;
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 266);
this.Controls.Add(this.comboBox);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);

}
#endregion

[STAThread]
static void Main()
{
Application.Run(new Form1());
}
}

public class Person
{
string _name;

public Person(string name)
{
this._name = name;
}

[Browsable(false)]
public string Name
{
get { return this._name; }
set { this._name = value; }
}
}
}
 
L

Lee Gillie

The error you see seems to make sense to me. When you bind to specific
DisplayMembers and ValueMembers, data binding must be able to find these
properties of your Person class. It would seem disabling Browsable
eliminates the programmatic discovery of your class members, their
properties, and values for an instance.

I wonder when both Display and Value member bindings are identical, why
even bind to an ArrayList and custom class, over the built in ItemList
of the ComboBox? Perhaps the example is contrived from something more
complex.

Setting the ValueMember property of a ComboBox to a name of a property
that is not browsable throws the following exception.

System.ArgumentException: Could not bind to the new display member.
Parameter name: newDisplayMember

It works fine if I set Browsable to true.
Has anyone encountered this before? Seems like a bug to me.

This is how I set up the DataSource:

ArrayList list = new ArrayList();
list.Add(new Person("John Doe"));
this.comboBox.DataSource = list;
this.comboBox.DisplayMember = "Name";
this.comboBox.ValueMember = "Name";

This is my Person class:

public class Person
{
string _name;
public Person(string name)
{
this._name = name;
}

[Browsable(false)]
public string Name
{
get { return this._name; }
set { this._name = value; }
}
}



Here is the complete code listing:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace BrowsableAttributeTest
{
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.ComboBox comboBox;
private System.ComponentModel.Container components = null;

public Form1()
{
InitializeComponent();

ArrayList list = new ArrayList();
list.Add(new Person("John Doe"));
this.comboBox.DataSource = list;
this.comboBox.DisplayMember = "Name";
try
{
this.comboBox.ValueMember = "Name";
}
catch(Exception e)
{
MessageBox.Show(e.ToString(), e.GetType().ToString());
}
}

protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.comboBox = new System.Windows.Forms.ComboBox();
this.SuspendLayout();
//
// comboBox
//
this.comboBox.DropDownStyle =
System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBox.Location = new System.Drawing.Point(24, 32);
this.comboBox.Name = "comboBox";
this.comboBox.Size = new System.Drawing.Size(184, 21);
this.comboBox.TabIndex = 0;
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 266);
this.Controls.Add(this.comboBox);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);

}
#endregion

[STAThread]
static void Main()
{
Application.Run(new Form1());
}
}

public class Person
{
string _name;

public Person(string name)
{
this._name = name;
}

[Browsable(false)]
public string Name
{
get { return this._name; }
set { this._name = value; }
}
}
}
 
E

eratchev

Thanks for the reply.

I thought the Browsable attribute was only used by the PropertyGrid. I
guess that's not the case.

This is example very similar to what I am doing. I want to bind to the
SelectedValue of the comboBox and I already have an ArrayList of
Persons.

this.comboBox.DataSource = list;
this.comboBox.DisplayMember = "Name";
this.comboBox.ValueMember = "Name";
this.comboBox.DataBindings.Add("SelectedValue", this, "PersonName");

Isn't this the prefered way of binding data to a combo box?
 
L

Lee Gillie

Isn't this the prefered way of binding data to a combo box?

It may be, but when display text and value are the same (which is almost
never the case) then implementation is trivial with the built in
itemlist. It is my own preference to implement in many times fewer lines
of code when all other considerations are the same. You could definitely
argue the point with me, I suppose primarily on general consistency.
 
E

eratchev

Actually I think I am missing something. How would you implement the
same functionality in less lines of code using the built in list of the
comboBox?
 
L

Lee Gillie

Actually I think I am missing something. How would you implement the
same functionality in less lines of code using the built in list of the
comboBox?

No ArrayList
No Person Class
No data binding

just "classic" ComboBox...

Dim cbx As New ComboBox
cbx.Items.Add("John")
cbx.Items.Add("Pete")
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top