2009-10-01 21 views
2

我有一個帶自定義列的DataGridView將ComboBox列添加到具有相同DataSource的DataGridView時出現ArgumentException

但是當我添加一個「DataGridViewComboBoxColumn」,並給它在我的模型類爲DataSource的名單,然後我有以下錯誤:

System.ArgumentException: DataGridViewComboBoxCell value is not valid.


新編輯: 4/9/2009 「更多詳細信息」

我有一個類叫SmsPart有這些屬性:

public class SmsPart 
{ 
    public int ID 
    public SmsPart Parent 
    public string Name 
    // and more 
} 

我所謂的 「GetSmsParts」 迴歸 「List<SmsPart>」 的方法。

我希望DataGridView中的Parent列爲ComboBoxColumn,以選擇哪個部分是選定部分的父級。

因此,對於這個原因,我提出「DataGridViewComboBoxColumn」,並設置它的數據源相同的數據源的孔的DataGridView「這是GetsmsParts方法」:

DataGridViewComboBoxColumn comboCulomn = new DataGridViewComboBoxColumn(); 
    comboCulomn.DataSource = listParts; 
    comboCulomn.DataPropertyName = "Parent"; 
    comboCulomn.DisplayMember = "Name"; 
    comboCulomn.ValueMember = "ID"; 
    comboCulomn.Name = "Parent"; 
    dgvParts.Columns.Add(comboCulomn); 

但我一直有這個錯誤消息:

System.ArgumentException: DataGridViewComboBoxCell value is not valid.

回答

4

拉昇的的ValueMember財產分配數據字段的名稱。當您指定值類型爲typeof(smsType)時,您沒有告訴ComboBox列哪個字段用於該值。

編輯
等待第二:是您smsType一些複雜型還是什麼?我不確定這裏是否有任何限制,但對於示例,您應該使用類似intstring左右的東西(任何您通常希望作爲數據庫字段存儲的內容)。

另外,當然,DataGridView的基礎數據源列(在您的示例中稱爲「類型」)的類型也必須與ValueMember的類型相同!

EDIT 2
關於你的第二個評論:想象一下,被稱爲包含(其中包括)所謂的「類型」一個欄是Integer類型的「任務型」數據庫表。您正在DataGridView中顯示該表的內容,並且希望用戶能夠從組合框中爲「類型」列選擇值。這是關於你正在談論的場景。

  1. 這是不可能的複雜類型存儲在像您使用的數據庫列的人,所以你不能在一個DataGridViewComboBoxColumn使用複雜類型的Value領域。
  2. 要爲整個網格執行數據綁定,您必須將網格綁定到數據庫表「tbl」。要創建DataGridViewComboBoxColumn,您需要爲列指定一個可能值的列表,並告訴列中DataGridView的數據源中的字段存儲所選值,哪個字段用作顯示值,哪個字段用作值它存儲在底層數據源的列中。

這意味着樣品中(假定該列的數據源所包含的屬性「值」和「姓名」):

DataGridViewComboBoxColumn col = new ... 
col.DataSource = columnDataSource; 
col.DisplayMember = "Name"; 
col.ValueMember = "Value"; 
col.DataPropertyName = "Type"; 

這是所有。但是,如果我記得正確,則指定給「ValueMember」的屬性類型不能是複雜類型(類/結構)...

+0

好吧,我使用自定義的類型,但並不複雜,它只是有兩個屬性「int和字符串」。對於第二個音符,我不明白你的意思,所以請爲我解釋。 非常感謝。 – 2009-10-01 13:20:27

+0

我更正了我的代碼,並將「ValueMember」設置爲「ID」,但它仍然有相同的錯誤。 – 2009-10-04 11:59:07

+0

我剛剛讀到DataGridView和Combo Box Column被設置爲相同的數據源!我不認爲這是可能的。儘管它們包含相同的數據,但嘗試創建兩個不同的數據源,一個用於網格,另一個用於該列。 – 2009-10-05 08:16:13

4

DataGridViewComboBoxColumn將輸入限制爲DataSource中的值。我有同樣的問題。我試圖在DGV之外設置字段值。我將DGV綁定到DataTable。如果我將DataRow [「somefield」]設置爲不在DataSource中的值,我將收到您收到的錯誤。

我最終創建了一個DataGridViewColumn的後代,它支持一個ComboBox編輯器,並允許不在DataSource中的值。

我可以發佈代碼,如果你想看到它。

編輯:這是一個組合框列例如

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

namespace YourNamespaceHere 
{ 
    /// <summary> 
    /// DataGridView TextBox column with Items support. 
    /// </summary> 

    public class DropTextBoxColumn : DataGridViewColumn 
    { 
     [Browsable(false)] 
     public IEnumerable<string> Items { get; set; } 

     public ComboBoxStyle DropDownStyle { get; set; } 

     public DropTextBoxColumn() : base(new DropTextBoxCell()) 
     { 
      DropDownStyle = ComboBoxStyle.DropDown; 
     } 

     private DataGridViewCell cellTemplate = new DropTextBoxCell(); 
     public override DataGridViewCell CellTemplate 
     { 
      get 
      { 
       return cellTemplate; 
      } 
      set 
      { 
       // Ensure that the cell used for the template is a DropTextBoxCell. 
       if (value != null && 
        !value.GetType().IsAssignableFrom(typeof(DropTextBoxCell))) 
       { 
        throw new InvalidCastException("Must be a DropTextBoxCell"); 
       } 
       cellTemplate = value; 
      } 
     } 
    } 

    public class DropTextBoxCell : DataGridViewTextBoxCell 
    { 
     [Browsable(false)] 
     public string[] Items { get; set; } 

     public DropTextBoxCell() : base() { } 


     protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts) 
     { 
      base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts); 

      //draw a drop down button 
      if ((cellState & DataGridViewElementStates.Selected) != 0) 
      { 
       var cb = cellBounds; 
       var r = new Rectangle(cb.Right - cb.Height, cb.Top, cb.Height, cb.Height); 
       //ComboBoxRenderer.DrawTextBox(graphics, cb, formattedValue as string, this.Style.Font ?? DataGridView.Font, ComboBoxState.Normal); 
       ComboBoxRenderer.DrawDropDownButton(graphics, r, ComboBoxState.Normal);    
      } 
     } 
     public override void InitializeEditingControl(int rowIndex, object 
      initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle) 
     { 
      // Set the value of the editing control to the current cell value. 
      base.InitializeEditingControl(rowIndex, initialFormattedValue, 
       dataGridViewCellStyle); 
      DropTextBoxEditingControl ctl = 
       DataGridView.EditingControl as DropTextBoxEditingControl; 

      var value = this.Value.ToString(); 

      ctl.Loading = true; 
      DropTextBoxColumn col = DataGridView.Columns[this.ColumnIndex] as DropTextBoxColumn; 
      ctl.DropDownStyle = col.DropDownStyle; 

      ctl.Items.Clear(); 
      if (col.Items != null) 
       ctl.Items.AddRange(col.Items.ToArray()); 

      ctl.EditingControlFormattedValue = value; 
      ctl.Loading = false; 

     } 

     public override Type EditType 
     { 
      get 
      { 
       // Return the type of the editing contol that CalendarCell uses. 
       return typeof(DropTextBoxEditingControl); 
      } 
     } 

     public override Type ValueType 
     { 
      get 
      { 
       // Return the type of the value that CalendarCell contains. 
       return typeof(string); 
      } 
     } 

     public override object DefaultNewRowValue 
     { 
      get 
      { 
       // Use the current date and time as the default value. 
       return string.Empty; 
      } 
     } 
    } 

    class DropTextBoxEditingControl : ComboBox, IDataGridViewEditingControl 
    { 
     DataGridView dataGridView; 
     private bool valueChanged = false; 
     int rowIndex; 
     public bool Loading { get; set; } 
     int originalIndex = -1; 

     public DropTextBoxEditingControl() 
     { 
      //this.Format = DateTimePickerFormat.Short; 
      DropDownStyle = ComboBoxStyle.DropDown; 
      FlatStyle = FlatStyle.Flat;  
     } 

     // Implements the IDataGridViewEditingControl.EditingControlFormattedValue 
     // property. 
     public object EditingControlFormattedValue 
     { 
      get 
      { 
       return Text; 
      } 
      set 
      { 

       if (value is String) 
       { 
        if (DropDownStyle == ComboBoxStyle.DropDown) 
         Text = value.ToString(); 
        else 
        { 
         SelectedIndex = originalIndex = Items.IndexOf(value);       
        }      
       } 
      } 
     } 

     // Implements the 
     // IDataGridViewEditingControl.GetEditingControlFormattedValue method. 
     public object GetEditingControlFormattedValue(
      DataGridViewDataErrorContexts context) 
     { 
      return EditingControlFormattedValue; 
     } 

     // Implements the 
     // IDataGridViewEditingControl.ApplyCellStyleToEditingControl method. 
     public void ApplyCellStyleToEditingControl(
      DataGridViewCellStyle dataGridViewCellStyle) 
     { 
      this.Font = dataGridViewCellStyle.Font; 
     } 

     // Implements the IDataGridViewEditingControl.EditingControlRowIndex 
     // property. 
     public int EditingControlRowIndex 
     { 
      get 
      { 
       return rowIndex; 
      } 
      set 
      { 
       rowIndex = value; 
      } 
     } 

     // Implements the IDataGridViewEditingControl.EditingControlWantsInputKey 
     // method. 
     public bool EditingControlWantsInputKey(
      Keys key, bool dataGridViewWantsInputKey) 
     { 
      // Let the DateTimePicker handle the keys listed. 
      //switch (key & Keys.KeyCode) 
      //{ 
      // case Keys.Left: 
      // case Keys.Up: 
      // case Keys.Down: 
      // case Keys.Right: 
      // case Keys.Home: 
      // case Keys.End: 
      // case Keys.PageDown: 
      // case Keys.PageUp: 
      //  return true; 
      // default: 
      //  return !dataGridViewWantsInputKey; 
      //} 

      return DroppedDown; 

     } 

     // Implements the IDataGridViewEditingControl.PrepareEditingControlForEdit 
     // method. 
     public void PrepareEditingControlForEdit(bool selectAll) 
     { 
      // No preparation needs to be done. 
     } 

     // Implements the IDataGridViewEditingControl 
     // .RepositionEditingControlOnValueChange property. 
     public bool RepositionEditingControlOnValueChange 
     { 
      get 
      { 
       return false; 
      } 
     } 

     // Implements the IDataGridViewEditingControl 
     // .EditingControlDataGridView property. 
     public DataGridView EditingControlDataGridView 
     { 
      get 
      { 
       return dataGridView; 
      } 
      set 
      { 
       dataGridView = value; 
      } 
     } 

     // Implements the IDataGridViewEditingControl 
     // .EditingControlValueChanged property. 
     public bool EditingControlValueChanged 
     { 
      get 
      { 
       return valueChanged; 
      } 
      set 
      { 
       valueChanged = value; 
      } 
     } 

     // Implements the IDataGridViewEditingControl 
     // .EditingPanelCursor property. 
     public Cursor EditingPanelCursor 
     { 
      get 
      { 
       return base.Cursor; 
      } 
     } 
     protected override void OnSelectedItemChanged(EventArgs e) 
     { 
      if (Loading) return; 

      // Notify the DataGridView that the contents of the cell 
      // have changed. 
      valueChanged = true; 
      this.EditingControlDataGridView.NotifyCurrentCellDirty(true); 
      base.OnSelectedItemChanged(e); 
     } 
     protected override void OnSelectedIndexChanged(EventArgs e) 
     { 
      if (Loading || DroppedDown) return; 

      // Notify the DataGridView that the contents of the cell 
      // have changed. 
      valueChanged = true; 
      this.EditingControlDataGridView.NotifyCurrentCellDirty(true); 
      base.OnSelectedIndexChanged(e); 


      SendKeys.Send("{ENTER}"); 
     } 
     protected override void OnTextChanged(EventArgs e) 
     { 
      if (Loading) return; 

      valueChanged = true; 
      this.EditingControlDataGridView.NotifyCurrentCellDirty(true); 
      base.OnTextChanged(e); 
     } 
     protected override void OnDropDownClosed(EventArgs e) 
     { 
      if (originalIndex != SelectedIndex) 
      { 
       valueChanged = true; 
       this.EditingControlDataGridView.NotifyCurrentCellDirty(true); 
      } 
      base.OnDropDownClosed(e); 

     } 
     protected override void OnDropDown(EventArgs e) 
     { 
      //set dropdown width to accomodate items 
      var g = CreateGraphics();  
      DropDownWidth = 
       Items.Cast<string>().Max(s => 
       { 
        var size = g.MeasureString(s, Font); 
        return size.Width.To<int>() + 30; 
       }); 
      base.OnDropDown(e); 
     } 
     protected override void OnEnter(EventArgs e) 
     { 
      base.OnEnter(e); 
      DroppedDown = true; 
     } 
    } 
} 

這裏的例子使用

var dc = new DropTextBoxColumn(); 
dc.Name = "FieldName"; 
dc.DataPropertyName = "FieldName"; 
dc.DropDownStyle = ComboBoxStyle.DropDownList; 

var items = dc.Items = new string[]{ "one", "two", "three" }; 
items.Insert(0, "<None>"); 

dc.Items = items; 
DirectGrid.Columns.Insert(1,dc); 
+0

我想看看這段代碼,謝謝! – Hoser 2009-10-02 13:41:02

+0

@Hoser - 添加樣本。希望能幫助到你! – Steve 2009-10-02 15:52:53

相關問題