I'm looking at ways to resolve an issue with a Winforms application, which uses a ComboBox control. Specifically, the ComboBox (Style=DropDownList) is bound to a datasource and, as the user navigates through some other data, the "Text" property of the ComboBox property is set - and the user can select some other value.
The trouble starts when the value I set the "Text" property to is not in the list of available items. It seems that nothing happens. Take the following simple example:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
myComboBox1.DropDownStyle = ComboBoxStyle.DropDownList;
//myComboBox1.Items.AddRange(new[] { "One", "Two", "Three" });
List<KeyValuePair<Int32, String>> values = new List<KeyValuePair<Int32, String>>();
values.Add(new KeyValuePair<Int32, String>(1, "One"));
values.Add(new KeyValuePair<Int32, String>(2, "Two"));
values.Add(new KeyValuePair<Int32, String>(3, "Three"));
myComboBox1.DataSource = values;
myComboBox1.ValueMember = "Key";
myComboBox1.DisplayMember = "Value";
button1.Click += (s, e) => { myComboBox1.Text = "Four"; };
button2.Click += (s, e) => { myComboBox1.SelectedIndex -= 1; };
}
}
public class MyComboBox : System.Windows.Forms.ComboBox
{
public override string Text
{
get { return base.Text; }
set { MessageBox.Show(value); base.Text = value; }
}
}
This technique is used throughout a large application, so when it was noticed that (in the example above) setting the "Text" to "Four" does nothing, I thought that maybe I could trap this and throw an exception. In reality, the application is peppered with code like this:
if (myDataRow.IsBlahNull())
myComboBox1.Text = "";
else
myComboBox1.Text = myDataRow.Blah;
Now, while I appreciate that setting "SelectedIndex = -1" would be better for the "IsNull" case, the fact remains that myDataRow.Blah may not be a valid value. Also, the application is written (and live) so the fewer changes the better.
So, my immediate thought was "let's override the Text property setter and check that the value is in the list". That, it turns out, is nothing like as simple as it would seem. The problem being that the "Text" property is set to all kinds of things, in all kinds of scenarios. For example, it's set when the DataSource property is assigned, or when the SelectedIndex is set to -1. Also, it's set to the string representation of the selected item - so if you happen to have a ComboBox control that's bound to a List of KeyValue pairs, you get the "Text" property set to something like "[Key,Value]". If it's bound to a DataTable/DataView, you get the string representation of the DataRow, and that gets even harder to detect.
It's at this point I thought that there might be another way to achieve the desired result (which is to detect the setting of the Text property to some invalid value - which does nothing).
Any ideas ?