2009-07-20 8 views
2

J'essaie d'utiliser DataGridView avec un objet métier. Voici un scénario simplifié: - appeler l'objet « recette », et il a un BindingList de quelques objets des ingrédients dans la recette - J'ai aussi une « base de données », qui est un BindingList de tous disponibles objets IngrédientsWinForms Databinding DataGridView avec ComboBoxColum

Je voudrais afficher un DataGridView de tous les ingrédients dans la recette, et permettre à l'utilisateur de sélectionner de nouveaux ingrédients à partir d'une liste déroulante dans le champ Nom. Lorsque j'essaie de configurer cela comme je le pense, le nom des ingrédients dans la recette ne s'affiche pas, bien que je puisse sélectionner dans le IngredientDB, et la sélection d'un nouvel ingrédient met à jour la liste dans la recette .

Comment obtenir le nom à afficher correctement?

Voici ce que j'ai jusqu'à présent:

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

ça marche pour moi, je reçois un menu déroulant avec du riz, la farine de blé entier et le beurre comme les valeurs. –

+0

Oui, mais la liste déroulante n'affiche pas les noms des ingrédients existants - eau et gin. – Hoser

Répondre

1

Vous n'avez pas les ingrédients Eau ou Gin dans votre liste «ingrédientDB». La source de données de DataGridView est définie sur la liste des ingrédients. Lorsque le formulaire est chargé, il crée automatiquement trois colonnes (Nom, Description, Quantité) en fonction des propriétés de votre objet métier (c'est-à-dire l'ingrédient). Ensuite, les rangées sont ajoutées en fonction de votre liste d'ingrédients ("Eau" et "Gin"). Ainsi, le résultat net est que vous avez 3 colonnes et 2 lignes dans votre DataGridView et il ressemble à ceci:

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

Cependant, vous insérez une DataGridViewComboBoxColumn dans la colonne 0 (la première colonne) et c'est là la question est.

La source de données de DataGridVidwComboBoxColumn est définie sur votre DataBs BindingSource, qui à son tour est définie sur "ingrédDB". Le "ingredientDB" ne contient que des entrées pour "riz", "farine de blé entier" et "beurre". Lorsque la colonne est affichée pour la première ligne, elle recherche un ingrédient avec le nom == "Eau" dans son DataSource (le "ingrédDD"). Cette "ingrédientDB" ne contient pas d'ingrédient pour l'eau et déclencherait normalement un DataGridViewDataErrorEvent. Cependant, vous manipulez l'événement vous-même et ne faites rien avec. Par conséquent, le ComboBox n'a rien dedans. La même chose arrive pour l'ingrédient "Gin". Aucun ingrédient "Gin" ne peut être trouvé dans votre "ingrédient DB", il ne peut donc pas être sélectionné.

Pour résoudre le problème, vous devez ajouter à la fois la « eau » et « Gin » à votre « 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

Le problème est que le DataGridViewComboBoxColumn n'est pas modifiable, il n'acceptera que la valeur de sa source de données.

Donc, vous avez 2 options:

  1. La solution facile: assurez-vous que tous les ingrédients possibles pour la recette sont définies avant de créer la recette et les choix de la DataGridViewComboBoxColumn.

  2. La solution la plus difficile: lorsque l'utilisateur modifie un ingrédient de la recette, gérer cet événement et changer le style de la Control sous-jacente de la DataGridViewComboBoxColumn-DropDown. Lorsque l'utilisateur a terminé l'édition, vérifiez s'il a entré une nouvelle valeur (pas dans la source de données) et l'ajoutez effectivement à la source de données (créez un nouvel ingrédient). Vous pouvez trouver des informations sur la mise en œuvre de cette approche here.

Questions connexes