Combobox не позволяет вводить пользовательский текст, если используется DataBinding
У меня есть следующий класс:
class Address
{
public string City {get; set;}
public string Street {get; set;}
}
и у меня есть форма с двумя комбобоксами на ней. Я привязываю эти comboboxes к классу Address:
CityComboBox.DataSource = GetCityDataSource();
StreetComboBox.DataSource = GetStreetDataSource();
Address address = new Address();
CityComboBox.DataBindings.Add("SelectedItem", address, "City");
StreetComboBox.DataBindings.Add("SelectedItem", address, "Street");
База данных городов и улиц не является полной, поэтому иногда пользователь должен писать пользовательские значения в combobox. Проблема в том, что привязка данных combobox не позволяет писать пользовательские значения в это поле. Есть ли обходной путь для такого поведения?
Спасибо заранее!
Ответы
Ответ 1
Это работает: (в вашем случае)
Установите DrowdownStyle
в Dropdown
и привяжите к свойству ComboBox Text
вместо SelectedItem
.
Для двух комбинированных ящиков вам нужно привязать текст к свойствам City
и Street
экземпляра класса Address
. Кажется, вы не хотите добавлять какие-либо элементы в List<string>
, возвращаемые методами GetCityDataSource()
или GetStreetDataSource()
.
Следовательно, поскольку свойство Text
target для привязки ниже не перепутано с (неизменяемым), коллекция элементов, связанная с вашим источником данных, следующие изменения должны сделать ваш код работать: (Я проверил сущность изменений кода ниже, используя 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! Подход выше работает только тогда, когда вы хотите использовать данные City и Street для простого пользовательского интерфейса. Вы не устанавливаете постоянную связь между адресными данными и объектами, для которых вы регистрируете адрес. Если вы хотите, чтобы ваши данные были нормализованы, вы хотели бы хранить внешние ключи для записей в таблицах City, Street (и, возможно, Zipcode).
С пользовательскими названиями улиц и городов вы получите много нечетких данных (например, Washington DC
, WASHINGTON D.C.
, St. Patricks rd.
, Saint Patrick road
и т.д.), что в будущем затруднит выполнение SQL запросов с использованием WHERE Street = [something]
. С нормализованными данными вы просто выполните WHERE StreetID = [specificID]
.
ИЗМЕНИТЬ
Если вы одновременно пытаетесь сделать две вещи в одном и том же диалоге пользовательского интерфейса (как для выбора улицы, так и для города, например, для профиля человека/компании, а также для обслуживания внутренних списков улиц и городов), тогда вы должны использовать другой подход.
Простейшим, возможно, является добавление кнопки "новый город" и "новая улица" рядом с вашим списком и обновление источника данных для выпадающего списка, когда пользователь предоставил правильный ввод в диалоговом окне.
Вы также можете добавить фиктивную запись в источник данных combobox со строкой "[добавить новый]" и использовать специальную обработку, когда этот элемент выбран. Поскольку этот подход подразумевает подделку исходного списка для комбо, он может легко стать немного грязным.
Пример приложения
Образец формы с привязкой к базе данных ComboBox, которая использует источник данных List<string>
![enter image description here]()
Ключевые свойства после выбора предопределенной улицы
![enter image description here]()
Ключевые свойства после выбора пользовательской улицы
![enter image description here]()
Ответ 2
Проверьте это:
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; }
}
Ответ 3
Вам нужно вставить новое значение в источник данных (если это массив, измените размер массива и добавьте новое значение в новый индекс, если это общий список, просто добавьте к нему новый элемент).
Ответ 4
Как я это делаю (я не использую привязку данных):
- Инициализировать экземпляр
List<T>
(может быть List<Address>
в вашем случае).
- Прочитайте элементы базы данных в
List<T>
.
- Заполните поля со списком, используя элементы, найденные в
List<T>
.
- Когда создается новый элемент, вставьте этот элемент в свою базу данных.
- Перезагрузка вверху (поддается процедуре, которую вы можете вызвать в любое время).
Если вам необходимо привязать данные, вы можете скрыть поле со списком и отобразить текстовое поле, пока пользователь не сохранит вашу информацию, но вам все равно нужно будет записать в свою базу данных и снова прочитать данные.
Ответ 5
Возможно, вы справитесь с ключевыми событиями, и когда они начнут вводить его, он добавит новый элемент?
Ответ 6
Проблема - наличие combobox привязка данных не позволяет писать пользовательские значения в это поле. Является существует обходное решение для этого поведения?
Так что не связывай это!
Напишите свои собственные методы для заполнения combobox и обработчика событий для редактирования элементов.