2009-07-20 2 views
2

Я пытаюсь использовать DataGridView с бизнес-объектом. Вот упрощенный вариант: - вызов объекта «Рецепт», и он имеет BindingList из нескольких Ингредиентов объектов в рецепте - У меня тоже есть «база данных», которая является BindingList все доступного Ингредиента объектовWinForms Databinding DataGridView с ComboBoxColum

Я хотел бы отобразить DataGridView всех ингредиентов в рецепте и позволить пользователю выбирать новые ингредиенты из поля со списком в поле «Имя».

Когда я пытаюсь настроить это так, как мне кажется, имя Ингредиентов в Рецепте не отображается, хотя я могу выбрать из IngredientDB, а выбор нового Ингредиента обновляет список в Рецепте ,

Как получить правильное отображение имени?

Вот что я до сих пор:

using System; 
using System.Collections.Generic; 
using System.Text; 
using System.ComponentModel; 
using System.Windows.Forms; 
using System.Drawing; 

namespace WindowsFormsApplication1 { 
    public class Ingredient { 

     private String name; 
     public String Name { 
      get { return name; } 
      set { name = value; } 
     } 

     private string description; 
     public String Description { 
      get { return description; } 
      set { description = value; } 
     } 

     private int amount; 
     public int Amount { 
      get { return amount; } 
      set { amount = value; } 
     } 

     public Ingredient(String n, String d, int a) { 
      Name = n; 
      Description = d; 
      Amount = a; 
     } 

     public Ingredient() { } 

    } 

    public class Data { 
     BindingList<Ingredient> ingredientDB = null; 
     public BindingList<Ingredient> IngredientDB { 
      get { return ingredientDB; } 
     } 

     public Data() { 
      ingredientDB = new BindingList<Ingredient>(); 
      ingredientDB.Add(new Ingredient("rice", "a grain", 2)); 
      ingredientDB.Add(new Ingredient("whole wheat flour", "for baking", 1)); 
      ingredientDB.Add(new Ingredient("butter", "fatty", 3)); 
     } 

    } 

    public class Recipe : INotifyPropertyChanged { 

     public String Name { 
      get; 
      set; 
     } 

     BindingList<Ingredient> ingredients = null; 
     public BindingList<Ingredient> Ingredients { 
      get { return ingredients; } 
      set { 
       ingredients = value; 
       NotifyPropertyChanged("Ingredients"); 
      } 
     } 

     public Recipe() { 
      Ingredients = new BindingList<Ingredient>(); 
      Ingredients.Add(new Ingredient("Water", "Wet", 2)); 
      Ingredients.Add(new Ingredient("Gin", "Yummy", 2)); 
     } 


     #region INotifyPropertyChanged Members 

     public event PropertyChangedEventHandler PropertyChanged; 
     private void NotifyPropertyChanged(String info) { 
      if (PropertyChanged != null) { 
       PropertyChanged(this, new PropertyChangedEventArgs(info)); 
      } 
     } 

     #endregion 
    } 

    public class myForm : Form { 

     private DataGridView dgv; 
     private BindingSource recipeBS; 
     private BindingSource dataBS; 
     public myForm() { 
      this.Height = 200; 
      this.Width = 400; 
      Recipe myRecipe = new Recipe(); 
      Data myData = new Data(); 
      recipeBS = new BindingSource(myRecipe, null); 
      dataBS = new BindingSource(myData, "IngredientDB"); 
      dgv = new DataGridView(); 
      dgv.Width = 400; 
      dgv.DataError += new 
      DataGridViewDataErrorEventHandler(DataGridView1_DataError); 
      dgv.DataSource = myRecipe.Ingredients; 
      // dgv.Columns.Remove("Name"); 
      DataGridViewComboBoxColumn comboboxColumn = new DataGridViewComboBoxColumn(); 
      comboboxColumn.DataPropertyName = "Name"; 
      comboboxColumn.HeaderText = "Name"; 
      comboboxColumn.DataSource = dataBS; 
      comboboxColumn.DisplayMember = "Name"; 
      comboboxColumn.ValueMember = "Name"; 
      dgv.Columns.Insert(0, comboboxColumn); 
      this.Controls.Add(dgv); 
     } 
     private void DataGridView1_DataError(object sender, DataGridViewDataErrorEventArgs anError) { } 

     [STAThreadAttribute()] 
     static void Main() { 
      Application.EnableVisualStyles(); 
      Application.Run(new myForm()); 
     } 
    } 


} 
+0

это работает для меня, я получаю выпадающий список с рисом, цельнозерновой муки и масло в качестве значений. –

+0

Да, но в поле со списком не отображаются имена существующих ингредиентов - вода и джины. – Hoser

ответ

1

У вас нет ингредиентов «Вода» или «Джин» в списке «ингредиентDB». Источник данных DataGridView установлен в список ингредиентов. Когда форма загружается, она автоматически создает 3 столбца (Имя, Описание, Сумма) на основе свойств вашего бизнес-объекта (т. Е. Ингредиент). Затем строки добавляются в соответствии с вашим списком ингредиентов («Вода» и «Джин»). Таким образом, чистый результат в том, что у вас есть 3 столбца и 2 строки в DataGridView, и это выглядит следующим образом:

Name | Description | Amount 
Water | Wet   | 2 
Gin | Yummy  | 2 

Однако, вы вставляете DataGridViewComboBoxColumn в колонке 0 (т.е. первый столбец) и там вопрос является.

Источник данных DataGridVidwComboBoxColumn настроен на ваш источник данных BBSSource, который, в свою очередь, установлен на «component.db». «Ингредиент ДБ» содержит только записи для «риса», «цельной пшеничной муки» и «сливочного масла». Когда столбец отображается для первой строки, он ищет Ингредиент с именем == «Вода» в своем источнике данных («componentDB»). Этот «ингредиентDB» не содержит Ингредиент для воды и обычно поднимает DataGridViewDataErrorEvent. Однако вы сами обрабатываете событие и ничего не делаете с ним. Поэтому в ComboBox ничего нет. То же самое происходит с ингредиентом «Джин». Ингредиент «Джин» не может быть найден в вашем «ингредиентеDB», поэтому его нельзя выбрать.

Чтобы устранить эту проблему, необходимо добавить как «вода» и «Джин» в свой «ingredientDB»:

public Data() 
{ 
    ingredientDB = new BindingList<Ingredient>(); 
    ingredientDB.Add(new Ingredient("rice", "a grain", 2)); 
    ingredientDB.Add(new Ingredient("whole wheat flour", "for baking", 1)); 
    ingredientDB.Add(new Ingredient("butter", "fatty", 3)); 
    ingredientDB.Add(new Ingredient("Water", "Wet", 2)); 
    ingredientDB.Add(new Ingredient("Gin", "Yummy", 2)); 
} 
1

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

Итак, у вас есть 2 варианта здесь:

  1. Простое решение: убедитесь, что все возможные ингредиенты для рецепта установлены перед созданием рецепта и выбрав их из DataGridViewComboBoxColumn.

  2. Чем сложнее решение: когда пользователь редактирует один ингредиент рецепта, обработать это событие и изменить стиль базовой Control от DataGridViewComboBoxColumn к DropDown. Когда пользователь закончит редактирование, проверьте, не ввел ли он новое значение (а не в источник данных) и эффективно добавит его в источник данных (создайте новый компонент). Вы можете найти информацию об осуществлении этого подхода here.

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