我有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值不是 有效的。
答案 0 :(得分:4)
尝试为ValueMember
的{{1}}属性分配数据字段的名称。当您指定值类型为clm2
时,您不会告诉ComboBox列要使用哪个字段作为值。
修改强> 当然, 编辑2 这意味着在示例中(假设列的数据源包含属性“Value”和“Name”): 这就是全部。但是,如果我没记错的话,分配给“ValueMember”的属性类型不能是复杂类型(类/结构)...
等一下:您的typeof(smsType)
是某种复杂类型还是什么?我不确定这里是否有任何限制,但对于示例,您应该使用类似smsType
或int
左右的内容(您通常希望存储为数据库字段的任何内容)。< / p>
string
基础数据源列的类型(在您的示例中称为“类型”)也必须与DataGridView
的类型相同!
在您的第二个评论:想象一个名为“tbl”的数据库表,其中包含一个名为“Type”的列,其类型为ValueMember
。您正在DataGridView中显示该表的内容,并且您希望用户能够从组合框中选择“类型”列的值。这是关于你正在讨论的情况。
Integer
中的Value
字段中使用复杂类型。DataGridViewComboBoxColumn
,您需要为列分配可能值的列表,并告诉列DataGridView的数据源中存储所选值的字段,该字段用作显示值,哪个字段是用作存储在基础数据源列中的值。DataGridViewComboBoxColumn
答案 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);