将ComboBox列添加到具有相同DataSource的DataGridView时的ArgumentException

时间:2009-10-01 12:23:31

标签: c# .net datagridview combobox datasource

我有DataGridView个自定义列。

但是,当我添加“DataGridViewComboBoxColumn”并将其模型类列表作为DataSource时,我遇到以下错误:

  

System.ArgumentException:   DataGridViewComboBoxCell值不是   有效的。


新编辑: 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”并将其 Datasource设置为与DataGridView相同的DataSource “这是 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值不是   有效的。

2 个答案:

答案 0 :(得分:4)

尝试为ValueMember的{​​{1}}属性分配数据字段的名称。当您指定值类型为clm2时,您不会告诉ComboBox列要使用哪个字段作为值。

修改
等一下:您的typeof(smsType)是某种复杂类型还是什么?我不确定这里是否有任何限制,但对于示例,您应该使用类似smsTypeint左右的内容(您通常希望存储为数据库字段的任何内容)。< / p>

当然,string基础数据源列的类型(在您的示例中称为“类型”)也必须与DataGridView的类型相同!

编辑2
在您的第二个评论:想象一个名为“tbl”的数据库表,其中包含一个名为“Type”的列,其类型为ValueMember。您正在DataGridView中显示该表的内容,并且您希望用户能够从组合框中选择“类型”列的值。这是关于你正在讨论的情况。

  1. 无法像您在数据库列中使用的那样存储复杂类型,因此您无法在Integer中的Value字段中使用复杂类型。
  2. 要对整个网格执行数据绑定,必须将网格绑定到数据库表“tbl”。要创建DataGridViewComboBoxColumn,您需要为列分配可能值的列表,并告诉列DataGridView的数据源中存储所选值的字段,该字段用作显示值,哪个字段是用作存储在基础数据源列中的值。
  3. 这意味着在示例中(假设列的数据源包含属性“Value”和“Name”):

    DataGridViewComboBoxColumn

    这就是全部。但是,如果我没记错的话,分配给“ValueMember”的属性类型不能是复杂类型(类/结构)...

答案 1 :(得分:4)

DataGridViewComboBoxColumn限制对DataSource中值的输入。我有同样的问题。我试图在DGV之外设置字段值。我将DGV绑定到DataTable。如果我将DataRow [“somefield”]设置为不在DataSource中的值,我将收到您收到的错误。

我最终创建了DataGridViewColumn的后代,它支持ComboBox编辑器并允许不在DataSource中的值。

如果您愿意,我可以发布代码。

编辑:这是一个ComboBox列示例

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);