2009-07-20 95 views
2

我正在嘗試使用DataGridView與業務對象。這裏有一個簡單的場景: - 調用對象的「配方」,它有幾個成分的的BindingList在配方 對象 - 我也有一個「數據庫」,這是所有可用的成分的的BindingList對象WinForms數據綁定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

我的作品,我拿飯,全麥麪粉和下拉黃油作爲價值。 – 2009-07-20 21:09:18

回答

1

您的「ingredientDB」列表中沒有水或杜松子酒成分。 DataGridView的數據源被設置爲成分列表。當表單被加載後,它會根據您的業務對象(即成分)的屬性自動創建3列(名稱,描述,金額)。然後根據您的成分列表(「水」和「杜松子酒」)添加行。所以,最終的結果是,你有3列和2列在您的DataGridView,它看起來像這樣:

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

然而,要插入一個DataGridViewComboBoxColumn成柱0(即第一列),而這也正是問題是。

DataGridVidwComboBoxColumn的數據源設置爲您的dataBs BindingSource,然後將其設置爲「ingredientDB」。 「ingredientsDB」僅包含「大米」,「全麥麪粉」和「黃油」的條目。當第一行顯示該列時,它會在DataSource中查找名稱爲「Water」的成分(「ingredientDB」)。這個「ingredientDB」不包含水成分,通常會引發DataGridViewDataErrorEvent。但是,您正在處理該事件,而不是採取任何措施。因此,ComboBox沒有任何內容。 「杜松子酒」成分也會發生同樣的情況。沒有「杜松子酒」成分可以在您的「ingredientDB」中找到,因此無法選擇。

要解決此問題,需要雙方的「水」和「晶晶」添加到你的「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是不可編輯的,所以它只會接受來自其數據源的值。

所以,你有兩個選擇在這裏:

  1. 最簡單的辦法:請確保配方中的所有成分,可能產生的配方,並從DataGridViewComboBoxColumn選擇他們之前設置。

  2. 更困難的解決辦法:當用戶編輯配方的一種成分,對此事件進行處理,改變DataGridViewComboBoxColumn的基本Control的風格DropDown。當用戶完成編輯時,檢查他是否輸入了新值(不在數據源中)並將其有效地添加到數據源(創建新成分)。您可以找到有關實施此方法的信息here