Установите выбранный элемент раскрывающегося списка в соответствии со значением строки в форме окна c # - PullRequest
0 голосов
/ 01 ноября 2018

В приложении Windows Form есть раскрывающийся список с именами производителей. После редактирования данной записи я хочу, чтобы пользователь также мог редактировать (изменять) производителя. Остальные значения работают нормально, и я могу легко назначить их текстовым полям, где они будут отредактированы и снова сохранены в базе данных.

Я запросил элемент раскрывающегося списка (название производителя, которое необходимо отредактировать) из базы данных, и теперь я хочу показать его как выбранный элемент в раскрывающемся списке. Я использовал следующий код для запроса конкретного производителя на основе идентификатора из базы данных и присвоения его строковой переменной manufacturerName.

DataTable dtMName = Products.SelectByManufacturerId(manufacturerId);
if (dtMName.Rows.Count > 0)
{
    foreach (DataRow item in dtMName.Rows)
    {
        string manufacturerName = item[0].ToString();
    }  
}

После отладки этого фрагмента кода string manfuacturerName содержит точное название производителя, которое я хочу изменить в раскрывающемся списке. Теперь я хочу отметить этот конкретный элемент как выбранный элемент в раскрывающемся списке. Я хочу передать его в список, чтобы он мог выбрать именно этого производителя в списке.

Пока что я попробовал следующий код, но он не работает.

childEditProduct.cmbManufacturer.SelectedIndex = childEditProduct.cmbManufacturer.FindString(manufacturerName);

Примечание. Первый элемент отмечен как selectedIndex при загрузке формы childEditProduct. Я также прокомментировал этот код, но ничего не работает. Есть ли какая-то проблема в моем коде, или позвольте мне попробовать что-то более эффективное, что может решить мою проблему.

Ответы [ 2 ]

0 голосов
/ 02 ноября 2018

Когда я загружал выпадающий список производителя в моем событии загрузки childForm, используя следующую функцию:

private void LoadManufacturers()
{
    cmbManufacturer.Items.Clear();
    DataTable dtManufacturers = DataAccess.Select("select manufacturername from tblmanufacturer order by manufacturername asc");
    foreach (DataRow dr in dtManufacturers.Rows)
    {
        cmbManufacturer.Items.Add(dr[0].ToString());
    }
    //cmbManufacturer.SelectedIndex = 0;
}

При загрузке производителей по событию загрузки страницы я также указывал выбранный индекс в раскрывающемся списке, используя код cmbManufacturer.SelectedIndex = 0;, который я закомментировал позже.

После этого я затем пересчитываю (повторно запрашиваю) выбранного производителя (который пользователь хочет обновить) в событии загрузки в раскрывающемся списке следующим образом:

private void frmChildEditProduct_Load(object sender, EventArgs e)
{
    LoadManufacturers(); // Calling the loadManufacturers function to load all the manufacturers to the dropdown list.

    string manufacturerID = lblManufacturerId.Text;

    DataTable dtMName = Products.SelectByManufacturerId(manufacturerID);
            if (dtMName.Rows.Count > 0)
            {
                foreach (DataRow manufacturer in dtMName.Rows)
                {
                    string manufacturerName = manufacturer[0].ToString();
                    cmbManufacturer.SelectedIndex = Convert.ToInt32(cmbManufacturer.FindStringExact(manufacturerName));
                }
            }
 }

И моя проблема была решена. Спасибо за поддержку, которую я получил на Stackoverflow.

0 голосов
/ 02 ноября 2018

Чтобы решить эту проблему и избежать в будущем более сложных кодов, было бы неплохо прочитать о 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

И снова, как я уже упоминал выше, первый код решит вашу проблему и облегчит вашу жизнь, но если вы привыкнете ко второму, вы увидите больше возможностей.

...