【问题标题】:ArgumentException when adding ComboBox column to DataGridView with same DataSource将 ComboBox 列添加到具有相同数据源的 DataGridView 时出现 ArgumentException
【发布时间】:2014-07-14 19:36:07
【问题描述】:

我有一个带有自定义列的DataGridView

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

System.ArgumentException: DataGridViewComboBoxCell 值不是 有效。


新编辑: 2009 年 4 月 9 日 “更多详情”

我有一个名为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 值不是 有效。

【问题讨论】:

    标签: c# .net datagridview combobox datasource


    【解决方案1】:

    尝试为clm2ValueMember 属性分配数据字段的名称。当您指定值类型为 typeof(smsType) 时,您并没有告诉 ComboBox 列该值使用哪个字段。

    编辑
    等一下:你的smsType 是不是一些复杂的类型?我不确定这里是否有任何限制,但对于示例,您应该使用 intstring 左右(您通常希望存储为数据库字段的任何内容)。

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

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

    1. 无法将复杂类型存储在您在数据库列中使用的类型中,因此您不能将复杂类型用于DataGridViewComboBoxColumn 中的Value 字段。
    2. 要对整个网格执行数据绑定,必须将网格绑定到数据库表“tbl”。要创建DataGridViewComboBoxColumn,您需要为该列分配一个可能值的列表,并告诉该列DataGridView 的数据源中的字段它将所选值存储到哪个字段用作显示值以及哪个字段用作存储在基础数据源列中的值。

    这意味着在示例中(假设列的数据源包含属性“Value”和“Name”):

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

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

    【讨论】:

    • 好的,我使用的是自定义类型,但并不复杂,它只有两个属性“int 和 string”。对于第二个注释,我不明白你的意思,所以请为我解释一下。非常感谢。
    • 我更正了我的代码并将“ValueMember”设置为“ID”,它是整数但仍然有相同的错误??.
    • 我刚刚读到DataGridView和Combo Box Column设置为同一个数据源!我不认为这是可能的。即使它们包含相同的数据,也要尝试创建两个不同的数据源,一个用于网格,一个用于列。
    【解决方案2】:

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

    【讨论】:

    • @Hoser - 添加了示例。希望对您有所帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-30
    • 1970-01-01
    • 1970-01-01
    • 2017-05-14
    相关资源
    最近更新 更多