Чтобы решить эту проблему и избежать в будущем более сложных кодов, было бы неплохо прочитать о DisplayMember
, ValueMember
свойствах.
Чтобы сделать эту работу с первыми двумя, просто сделайте это:
public class Manufacturer
{
public int Id { get; set; } //Important to have get/set othervise DisplayMember and ValueMember properties will not work
public string Name { get; set; } //Important to have get/set othervise DisplayMember and ValueMember properties will not work
public static List<Manufacturer> GetAllManufacturers()
{
List<Manufacturer> list = new List<Manufacturer>();
//Read manufacturers one by one, create object of Manufacturer and then add that object to list
return list;
}
}
//This code below set in form constructor or on load
cmbManufacturer.DisplayMember = "Name";
cmbManufacturer.ValueMember = "Id;
cmbManufacturer.DataSource = Manufacturer.GetAllManufacturers();
//And now when you need to select manufacturer by id you do
cmbManufacturer.SelectedValue = 6; //Will select manufacturer which has id 6
//If you have updated your manufacturers in runtime and want to again load everything in combobox just do
cmbManufacturer.DataSource = Manufacturer.GetAllManufacturers();
Выше простое использование этих двух свойств, а внизу я покажу вам более продвинутое.
Мы перепишем наш Manufacturer
класс следующим образом:
public class Manufacturer
{
public int Id { get; set; }
public string Name { get; set; }
public string City { get; set; }
public string PersonInCharge { get; set; }
public string PhoneNumber { get; set; }
public static List<Tuple<string, Manufacturer>> GetAllManufacturers()
{
//This one i will make example with interaction to database
List<Tuple<string, Manufacturer>> list = new List<Tuple<string, Manufacturer>>();
using(SqlConnection con = new SqlConnection("SomeSqlString"))
{
con.Open();
using(SqlCommand cmd = new SqlCommand("Select Id, Name, City, Person, Phone from Manufacturers", con))
{
SqlDataReader dr = cmd.ExecuteReader();
while(dr.Read()) //Will read one by one line
{
Manufacturer m = new Manufacturer();
m.Id = Convert.ToInt32(dr[0]);
m.Name = dr[1].ToString();
m.City = dr[2].ToString();
m.PersonInCharge = dr[3].ToString();
m.PhoneNumber = dr[4].ToString();
list.Add(new Tuple<string, Manufacturer>(m.Id, m));
}
}
}
return list;
}
}
С таким классом у нас есть дополнительная информация о нашем производителе, но как ее отобразить или сохранить? Ну вот и наш тег пришел.
Tag is type of object which holds any additional object you want
Итак, теперь мы связываем наши DisplayMember
и ValueMember
, как мы это делали выше, но теперь вместо прямого связывания источника данных мы сначала сохраним наш список в отдельной переменной:
List<Tuple<string, Manufacturers>> man = Manufacturer.GetAllManufacturers();
cmbManufacturer.DisplayMember = "item1"; //We use item1 and item2 since those are names of variables in Tuple<T>
cmbManufacturer.ValueMember = "item2"; //We use item1 and item2 since those are names of variables in Tuple<T>
cmbManufacturer.DataSource = man;
Таким образом, мы присвоили item1
, который является m.Name
, который является именем нашего Производителя как DisplayMember
, и присвоил item2
, который является Manufacturer
классом, который содержит всю другую информацию о нашем производителе (Да, мы можем сделать это так как ValueMember
это тип object
).
Теперь у нас есть заполненный комбинированный список, но мы не сможем легко выбрать элемент, подобный этому:
cmbManufacturer.SelectedValue = 6; //Will select manufacturer which has id 9
Так как наш SelectedValue
не представляет int
, а Manufacturer
.
Что мы можем сделать, чтобы решить эту проблему, так это создать функцию внутри формы, которая выберет ее.
private void SelectManufacturerById(int id)
{
for(int i = 0; i < cmbManufacturer.Items.Count; i++)
{
Manufacturer m = (cmbManufacturer.Items[i] as Tuple<string, Manufacturer>).item2;
if(m.Id == id)
{
cmbManufacturer.SelectedItem = cmbManufacturer.Items[i];
return;
}
}
// Here throw some message since it couldn't find it
}
И, возможно, у вас до сих пор нет смысла вообще использовать свойство tag, поскольку это только усложняет задачу, но это не так, поскольку при выборе по коду идентификатора вы можете легко изменить его на другое значение в Manufacturer
класс, также вы можете добавить еще немного кода к вашему классу производителя, как
public void Update()
{
using(SqlConnection con = new SqlConnection("SomeSqlString"))
{
con.Open();
using(SqlCommand cmd = new SqlCommand("Update Manufacturers set Id = @id ....", con))
{
cmd.Parameters.AddWithValue("@id", m.Id);
//Assigning other paramterts
cmd.ExecuteNonQuery();
//Display message of success
}
}
}
и затем внутри формы с помощью выпадающего списка вы делаете что-то вроде этого
Manufacturer m = cmbManufacturer.SelectedValue as Manufacturer; //We will get currently selected manufacturer inside combobox
m.Name = "Here we change name of it";
m.Update(); //Here we run function inside our class and it will update database and new name
И снова, как я уже упоминал выше, первый код решит вашу проблему и облегчит вашу жизнь, но если вы привыкнете ко второму, вы увидите больше возможностей.