Combobox doesn't allow enter custom text if DataBinding is used
class Address
{
public string City {get; set;}
public string Street {get; set;}
}
and I have a form with 2 comboboxes on it. I bind these comboboxes to Address class:
CityComboBox.DataSource = GetCityDataSource();
StreetComboBox.DataSource = GetStreetDataSource();
Address address = new Address();
CityComboBox.DataBindings.Add("SelectedItem", address, "City");
StreetComboBox.DataBindings.Add("SelectedItem", address, "Street");
The da开发者_StackOverflow中文版tabase of Cities and Streets is not complete, so sometimes user should write custom values to combobox. The problem is - having combobox databindings doesn't allow to write custom values to this combobox. Is there a workaround for this behaviour?
Thanks in advance!This works: (in your case)
Set the DrowdownStyle
to Dropdown
and bind to the ComboBox's Text
property instead of SelectedItem
.
For the two comboboxes, you appear to want to bind the text to the City
and Street
properties of an instance of the Address
class. You don't seem to want to append any items in the List<string>
returned by the GetCityDataSource()
or GetStreetDataSource()
methods.
Therefore, since the Text
target property of the binding below isn't entangled with the (unchangeable) items collection associated with your datasource, the following modifications should make your code work: (I've verified the essense of the code changes below using VS 2010).
CityComboBox.DataSource = GetCityDataSource();
StreetComboBox.DataSource = GetStreetDataSource();
Address address = new Address();
CityComboBox.DropDownStyle = ComboBoxStyle.DropDown
CityComboBox.DataBindings.Add("Text", address, "City");
StreetComboBox.DropDownStyle = ComboBoxStyle.DropDown
StreetComboBox.DataBindings.Add("Text", address, "Street");
PS! The approach above only works when you want to use the City and Street data for simple UI-guidance. You are not establishing a permanent relationship between the address data and the objects for which you register an address. If you want to keep your data normalized then you would wish to store foreign keys to the entries in the City, Street (and perhaps Zipcode) tables.
With user defined street and city names, you will get a lot of fuzzy data (e.g. Washington DC
, WASHINGTON D.C.
, St. Patricks rd.
, Saint Patrick's road
etc.) which in the future will make it difficult to execute SQL queries using WHERE Street = [something]
. With normalized data you would simply do a WHERE StreetID = [specificID]
.
EDIT
If you are trying to do two things at the same time within the same UI dialog (both selection of street and city for e.g. a person/company profile as well as maintenance of your application's internal street and city lists), then you have to use a different approach.
The simplest is probably to add a "new city" and a "new street" button next to your combobox and update the datasource for the combobox when the user has provided the proper input in a dialog.
You could also add a dummy entry to the combobox data source with the string "[add New]", and use special handling when this item is selected. Since this approach involves tampering with the source list for the combo, it can easily get a little messy.
Sample App
A sample form with a databound ComboBox which uses a List<string>
data source
Key properties after selecting a predefined street
Key properties after selecting a custom street
Check this out:
public partial class Form1 : Form
{
BindingList<Address> list;
public Form1()
{
InitializeComponent();
list = new BindingList<Address>();
//lets add some example data:
list.Add(new Address{ City = "London", Street = "Street 111" });
list.Add(new Address { City = "Barcelona", Street = "Street 222" });
comboBox1.DataSource = list;
//I am not sure what you want to show (and what to use as a value). You can change this!
comboBox1.DisplayMember = "Street";
comboBox1.ValueMember = "City";
}
private void button1_Click(object sender, EventArgs e)
{
//adding new object to the list:
string _city = textBox1.Text;
string _street = textBox2.Text;
if (_city != String.Empty && _street != String.Empty)
{
list.Add(new Address { City = _city, Street = _street });
textBox1.Text = "";
textBox2.Text = "";
}
}
}
class Address
{
public string City { get; set; }
public string Street { get; set; }
}
You have to insert new value into data source (if this is a array resize an array, and add the new value at the new index, if this is a generi list, simply add new item to it).
How I do it (I do not use data binding):
- Initialize an instance of
List<T>
(can beList<Address>
in your case). - Read the database items into a
List<T>
. - Populate your combo boxes using the items found in the
List<T>
. - When a new item is created, insert that item into your database.
- Restart at the top (lends itself to a procedure you can call anytime).
If you must data bind, you could hide the combo box and pop up a text box until the user saves your information, but you'd still need to write to your database and read the data in again.
You could perhaps handle the keyevents and when they start typing it then adds a new element?
The problem is - having combobox databindings doesn't allow to write custom values to this combobox. Is there a workaround for this behaviour?
So don't bind it! Write your own methods to fill combobox and event handler for editing items.
精彩评论