2015-06-19 6 views
0

Я надеюсь, что кто-то может помочь мне с неясной проблемой, которая меня совершенно смущает.Связанный DataGridView: DataGridViewComboBoxColumn меняется на другое значение, когда я нажимаю на него.

Я хочу настроить DataGridView, который позволяет пользователю выбирать параметр из DataGridViewComboBoxColumn и для объекта, который является источником данных для DataGridView, для обновления с объектом, который пользователь выбирает в ComboBox.

[NB Я хочу, чтобы DataGridViewComboBoxColumn отображал больше, чем одно свойство в раскрывающемся списке, поэтому я использую DataTable в качестве источника данных DataGridViewComboBoxColumn. Другими словами, я хочу, чтобы они увидели описание, которое представляет собой комбинацию других свойств, объединенных вместе.]

Мой код работает, но когда я нажимаю вне ячейки ComboBox, значение автоматически устанавливается (оно возвращается к первый элемент в BindingList). Я не могу заставить его придерживаться значения, которое выбрал пользователь. В конечном счете, неверный экземпляр объекта присваивается DataSource DataGridView.

Я бы опубликовал рис, но мне не хватает репутации.

Итак, мой вопрос в том, почему DataGridViewComboBoxColumn переключается на первый элемент в своем источнике данных (DataTable), когда я нажимаю кнопку вне ячейки. Как я могу заставить его сохранить выбранную опцию в ячейке. Я абсолютно БЕСПЛАТНО.

Надеюсь, вы сможете опубликовать этот код намного до веб-сайта StackOverflow, не раздражая всех. Я попытался создать подходящий общий пример, чтобы помочь другим душам попытаться выяснить, как выбрать и присвоить объект свойству другого объекта, используя DataGridViewComboBoxColumn. Поэтому, надеюсь, это полезно кому-то другому. Я также пытался сделать это относительно легко воссоздать, если кто-то должен решить эту проблему.

Я пробовал всевозможные вещи, в том числе с использованием списка как источника данных DataGridViewComboBoxColumn, делающего что-то с событием CurrentCellDirtyStateChanged - все безрезультатно.

Вот мои 2 класса:

public class CarPartChoice 
    { 
     public string Name { get; set; } 
     public int Value { get; set; } 
     public string Comment {get; set;} 

     public CarPartChoice(string name, int value, string comment) 
     { 
      Name = name; 
      Value = value; 
      Comment = comment; 
     } 
    } 

    public class Car 
    { 
     public string Manufacturer { get; set; } 
     public string Model { get; set; } 
     public CarPartChoice WheelChoice {get; set;} 

     public Car(string maker, string model, CarPartChoice wheel) 
     { 
      Manufacturer = maker; 
      Model = model; 
      WheelChoice = wheel; 
     } 

     public Car(string maker, string model) 
     { 
      Manufacturer = maker; 
      Model = model; 
     } 
    } 

    public static class GlobalVariables 
    { 
     public static BindingList<CarPartChoice> GlobalChoiceList { get; set; } 
     public static BindingList<Car> GlobalCarsList { get; set; } 
    } 

И вот я создаю мой DataGridView:

 private void Form1_Load(object sender, EventArgs e) 
     { 
      //Setup the wheel choices to be selected from the DataGridViewComboBoxColumn. 
      CarPartChoice myWheelChoice = new CarPartChoice("Chrome", 19, "This is the chromes wheels option."); 
      CarPartChoice myWheelChoice2 = new CarPartChoice("HubCaps", 16, "This is the nasty plastic hubcaps option."); 
      BindingList<CarPartChoice> tempBLChoice = new BindingList<CarPartChoice>(); 
      tempBLChoice.Add(myWheelChoice); 
      tempBLChoice.Add(myWheelChoice2); 
      GlobalVariables.GlobalChoiceList = tempBLChoice; 

      //Setup the cars to populate the datagridview. 
      Car car1 = new Car("Vauxhall", "Astra"); 
      Car car2 = new Car("Mercedes", "S-class"); 
      BindingList<Car> tempListCars = new BindingList<Car>(); 
      tempListCars.Add(car1); 
      tempListCars.Add(car2); 
      GlobalVariables.GlobalCarsList = tempListCars; 

      dataGridView1.AutoGenerateColumns = false; 
      dataGridView1.CurrentCellDirtyStateChanged += new EventHandler(dataGridView1_CurrentCellDirtyStateChanged); 

      // Set up 2 DataGridViewTextBox columns, one to show the manufacturer and the other to show the model. 
      DataGridViewTextBoxColumn manufacturer_col = new DataGridViewTextBoxColumn(); 
      manufacturer_col.DataPropertyName = "Manufacturer"; 
      manufacturer_col.Name = "Manufacturer"; 
      manufacturer_col.HeaderText = "Manufacturer"; 
      DataGridViewTextBoxColumn model_col = new DataGridViewTextBoxColumn(); 
      model_col.DataPropertyName = "Model"; 
      model_col.Name = "Model"; 
      model_col.HeaderText = "Model"; 

      // Create a DataTable to hold the Wheel options available for the user to choose from. This DT will be the DataSource for the 
      // ...combobox column 
      DataTable wheelChoices = new DataTable(); 
      DataColumn choice = new DataColumn("Choice", typeof(CarPartChoice)); 
      DataColumn choiceDescription = new DataColumn("Description", typeof(String)); 
      wheelChoices.Columns.Add(choice); 
      wheelChoices.Columns.Add(choiceDescription); 
      foreach (CarPartChoice wheelchoice in GlobalVariables.GlobalChoiceList) 
      { 
       wheelChoices.Rows.Add(wheelchoice, wheelchoice.Name + " - " + wheelchoice.Value.ToString() + " - " + wheelchoice.Comment); 
      } 

      // Create the Combobox column, populated with the wheel options so that user can pick one. 
      DataGridViewComboBoxColumn wheelOption_col = new DataGridViewComboBoxColumn(); 
      wheelOption_col.DataPropertyName = "WheelChoice"; 
      wheelOption_col.Name = "WheelChoice"; 
      wheelOption_col.DataSource = wheelChoices; 
      wheelOption_col.ValueMember = "Choice"; 
      wheelOption_col.DisplayMember = "Description"; 
      wheelOption_col.ValueType = typeof(CarPartChoice); 

      // Add the columns and set the datasource for the DGV. 
      dataGridView1.Columns.Add(manufacturer_col); 
      dataGridView1.Columns.Add(model_col); 
      dataGridView1.Columns.Add(wheelOption_col); 
      dataGridView1.DataSource = GlobalVariables.GlobalCarsList; 
     } 

UPDATE: Я пытался использовать "BindingSource" объект и настройка источника данных из BindingSource к DataTable. Это не имело никакого значения. Я также пытался получить автомобиль для реализации интерфейса «INotifyPropertyChanged», и это не имело никакого значения.

Единственное, что я заметил, это то, что элемент Car в datagridview ДОЛЖЕН получить его свойство WheelChoice. Объекты Car IS INDEED обновлены со значением, которое я выбрал из ComboBox. Я думаю, что это просто проблема с отображением, и DataGridViewComboBoxColumn просто не заполнен правильным значением. Все еще сбито с толку.

+0

Это всегда происходит при нажатии или только при выпадающем меню? – TaW

+0

Обход проблемы: добавьте пустой обработчик событий DataError: 'this.dataGridView1.DataError + = (sender, e) => {};' – Fabio

+0

Привет, TaW: это происходит ПОСЛЕ того, как я выбрал из раскрывающегося списка и нажал на другой элемент управления. Другими словами, я выбрал свой вариант из раскрывающегося списка, что вызвало заполнение поля и выпадающего списка. Моя выбранная опция остается в элементе управления, пока я не щелкнув нигде вне раскрывающегося списка. Как только я это сделаю, значение в элементе управления автоматически изменится. –

ответ

0

Спасибо тем, кто оставил комментарии. Я нашел ответ в конце.

Ответ на этот вопрос - просто определить переопределенный метод «ToString()» для моего класса «CarPartChoice» (т. Е. Класс, который используется для предоставления элементов, подлежащих поиску, путем нажатия на ComboBoxColumn). Я предполагаю, что у меня возникли проблемы с форматированием моей ячейки с хорошей строкой, когда я отошел от нее.

Итак, для тех, кто когда-либо хочет это сделать в будущем, приведен полный пример того, как вы можете использовать datagridview для обновления списка объектов определенного класса и использования DataGridViewComboBoxColumn, чтобы предоставить пользователю выбор объектов и их выбранного объекта (который они выбрали из раскрывающегося списка), который будет занесен в список (точнее: в поле объекта в списке, который относится к типу объекта, который выбирается пользователем в выпадающем списке). Да, я знаю, что это очень ужасное предложение.

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

С наилучшими пожеланиями.

public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      //Setup the wheel choices to be selected from the DataGridViewComboBoxColumn. 
      CarPartChoice myWheelChoice = new CarPartChoice("Chrome", 19, "This is the chromes wheels option."); 
      CarPartChoice myWheelChoice2 = new CarPartChoice("HubCaps", 16, "This is the nasty plastic hubcaps option."); 
      CarPartChoice myWheelChoice3 = new CarPartChoice("Iron", 15, "These are metal wheels."); 
      CarPartChoice myWheelChoice4 = new CarPartChoice("Spoked", 15, "This is the fancy classic hubcaps option."); 
      CarPartChoice myWheelChoice5 = new CarPartChoice("solid", 13, "This wheels has no spokes or holes."); 
      CarPartChoice myWheelChoice6 = new CarPartChoice("SpaceHubCaps", 17, "Newly developed space hubcaps."); 

      BindingList<CarPartChoice> tempBLChoice = new BindingList<CarPartChoice>(); 
      tempBLChoice.Add(myWheelChoice); 
      tempBLChoice.Add(myWheelChoice2); 
      tempBLChoice.Add(myWheelChoice3); 
      tempBLChoice.Add(myWheelChoice4); 
      tempBLChoice.Add(myWheelChoice5); 
      tempBLChoice.Add(myWheelChoice6); 

      GlobalVariables.GlobalChoiceList = tempBLChoice; 

      //Setup the cars to populate the datagridview. 
      Car car1 = new Car("Vauxhall", "Astra"); 
      Car car2 = new Car("Mercedes", "S-class"); 
      BindingList<Car> tempListCars = new BindingList<Car>(); 
      tempListCars.Add(car1); 
      tempListCars.Add(car2); 
      GlobalVariables.GlobalCarsList = tempListCars; 

      dataGridView1.AutoGenerateColumns = false; 
      dataGridView1.CurrentCellDirtyStateChanged += new EventHandler(dataGridView1_CurrentCellDirtyStateChanged); 


      // Set up 2 DataGridViewTextBox columns, one to show the manufacturer and the other to show the model. 
      DataGridViewTextBoxColumn manufacturer_col = new DataGridViewTextBoxColumn(); 
      manufacturer_col.DataPropertyName = "Manufacturer"; 
      manufacturer_col.Name = "Manufacturer"; 
      manufacturer_col.HeaderText = "Manufacturer"; 
      DataGridViewTextBoxColumn model_col = new DataGridViewTextBoxColumn(); 
      model_col.DataPropertyName = "Model"; 
      model_col.Name = "Model"; 
      model_col.HeaderText = "Model"; 

      // Create a DataTable to hold the Wheel options available for the user to choose from. This DT will be the DataSource for the 
      // ...combobox column 
      DataTable wheelChoices = new DataTable(); 
      DataColumn choice = new DataColumn("Choice", typeof(CarPartChoice)); 
      DataColumn choiceDescription = new DataColumn("Description", typeof(String)); 
      wheelChoices.Columns.Add(choice); 
      wheelChoices.Columns.Add(choiceDescription); 

      foreach (CarPartChoice wheelchoice in GlobalVariables.GlobalChoiceList) 
      { 
       wheelChoices.Rows.Add(wheelchoice, wheelchoice.Name + " - " + wheelchoice.Value.ToString() + " - " + wheelchoice.Comment); 
      } 

      // Create the Combobox column, populated with the wheel options so that user can pick one. 
      DataGridViewComboBoxColumn wheelOption_col = new DataGridViewComboBoxColumn(); 
      wheelOption_col.DataPropertyName = "WheelChoice"; 
      wheelOption_col.DataSource = wheelChoices; 
      wheelOption_col.ValueMember = "Choice"; 
      wheelOption_col.DisplayMember = "Description"; 
      wheelOption_col.ValueType = typeof(CarPartChoice); 

      // Add the columns and set the datasource for the DGV. 
      dataGridView1.Columns.Add(manufacturer_col); 
      dataGridView1.Columns.Add(model_col); 
      dataGridView1.Columns.Add(wheelOption_col); 
      dataGridView1.DataSource = GlobalVariables.GlobalCarsList; 
     } 

     void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e) 
     { 
      var grid = sender as DataGridView; 
      if (grid.IsCurrentCellDirty) 
       grid.CommitEdit(DataGridViewDataErrorContexts.Commit); 
     } 
    } 

    public class CarPartChoice 
    { 
     public string Name { get; set; } 
     public int Value { get; set; } 
     public string Comment { get; set; } 

     public CarPartChoice(string name, int value, string comment) 
     { 
      Name = name; 
      Value = value; 
      Comment = comment; 
     } 

     public override string ToString() 
     { 
      return Name.ToString() + " - " + Value.ToString() + " - " + Comment.ToString(); 
     } 
    } 

    public class Car 
    { 
     public string Manufacturer { get; set; } 
     public string Model {get; set; } 
     public CarPartChoice WheelChoice { get; set; } 

     public Car(string maker, string model, CarPartChoice wheel) 
     { 
      Manufacturer = maker; 
      Model = model; 
      WheelChoice = wheel; 
     } 

     public Car(string maker, string model) 
     { 
      Manufacturer = maker; 
      Model = model; 
     } 
    } 

    public static class GlobalVariables 
    { 
     public static BindingList<CarPartChoice> GlobalChoiceList { get; set; } 
     public static BindingList<Car> GlobalCarsList { get; set; } 
    } 

 Смежные вопросы

  • Нет связанных вопросов^_^