如何在DataGridView中填充自定义列单元格
本文关键字:自定义 单元格 填充 DataGridView | 更新日期: 2023-09-27 18:15:25
我设法向DGV添加另一列,但现在我在用值填充单元格时遇到了麻烦。
到目前为止我写的是:
// add new column
int lineItemsColumnIndex = dataGridView1.Columns.Add("LineItems", "Line Items");
// set up nested DataGridView for orders and lineitems.
foreach (DataGridViewRow row in dataGridView1.Rows)
{
List<LineItem> lineItems = ((Order)(row.DataBoundItem)).lineItems;
string cellValue = "";
for(int i=0; i<lineItems.Count; i++){
FoodMenuItem menuItem = new FoodMenuItem(lineItems[i].menuItemID);
cellValue += lineItems[i].quantity.ToString() + "x " + menuItem.title + (i==lineItems.Count-1 ? "." : ", ");
}
row.Cells[lineItemsColumnIndex].Value = cellValue;
}
如何将数据放入自定义列?
应该是这样的…
您确定代码运行时DGV已经有行了吗?
但是你还可以考虑另一件事:
你可以为你的数据对象创建包装器,和/或添加一个自定义类型描述符,为你的数据添加一个新的属性,可以被。net数据绑定使用,这样你就不必手动设置列了…
像这样:
public class Wrapper<T> : System.ComponentModel.ICustomTypeDescriptor
{
public T wrappee { get; private set; }
private Dictionary<String, Func<T, String>> ext_get;
public Wrapper(T theObjectWeWantToWrap,Dictionary<String,Func<T,String>> theSpecsForTheAdditionalColumns)
{
wrappee = theObjectWeWantToWrap;
ext_get = theSpecsForTheAdditionalColumns;
}
System.ComponentModel.AttributeCollection System.ComponentModel.ICustomTypeDescriptor.GetAttributes()
{
return TypeDescriptor.GetAttributes(wrappee,true);
}
string System.ComponentModel.ICustomTypeDescriptor.GetClassName()
{
return TypeDescriptor.GetClassName(wrappee, true);
}
string System.ComponentModel.ICustomTypeDescriptor.GetComponentName()
{
return TypeDescriptor.GetComponentName(wrappee, true);
}
System.ComponentModel.TypeConverter System.ComponentModel.ICustomTypeDescriptor.GetConverter()
{
return TypeDescriptor.GetConverter(wrappee, true);
}
System.ComponentModel.EventDescriptor System.ComponentModel.ICustomTypeDescriptor.GetDefaultEvent()
{
return TypeDescriptor.GetDefaultEvent(wrappee, true);
}
System.ComponentModel.PropertyDescriptor System.ComponentModel.ICustomTypeDescriptor.GetDefaultProperty()
{
return TypeDescriptor.GetDefaultProperty(wrappee, true);
}
object System.ComponentModel.ICustomTypeDescriptor.GetEditor(Type editorBaseType)
{
return TypeDescriptor.GetEditor(wrappee, editorBaseType, true);
}
System.ComponentModel.EventDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetEvents(Attribute[] attributes)
{
return TypeDescriptor.GetEvents(wrappee, attributes, true);
}
System.ComponentModel.EventDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetEvents()
{
return TypeDescriptor.GetEvents(wrappee, true);
}
System.ComponentModel.PropertyDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetProperties(Attribute[] attributes)
{
return filterProps(TypeDescriptor.GetProperties(wrappee, attributes, true));
}
System.ComponentModel.PropertyDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetProperties()
{
return filterProps(TypeDescriptor.GetProperties(wrappee, true));
}
object System.ComponentModel.ICustomTypeDescriptor.GetPropertyOwner(System.ComponentModel.PropertyDescriptor pd)
{
if (ext_get.Keys.Contains(pd.Name))
return this;
return wrappee;
}
private PropertyDescriptorCollection filterProps(PropertyDescriptorCollection propertyDescriptorCollection)
{
List<PropertyDescriptor> pd_list = new List<PropertyDescriptor>(propertyDescriptorCollection.Cast<PropertyDescriptor>().Where(x=>!ext_get.Keys.Contains(x.DisplayName)));
foreach (var item in ext_get)
{
pd_list.Add(new MyPropertyDescriptor<T>(item));
}
return new PropertyDescriptorCollection(pd_list.ToArray());
}
private class MyPropertyDescriptor<T> : System.ComponentModel.PropertyDescriptor
{
public MyPropertyDescriptor(KeyValuePair<string,Func<T,string>>kvp)
:base(kvp.Key,new Attribute[]{})
{
f = kvp.Value;
}
private Func<T, String> f;
public override bool CanResetValue(object component)
{
return false;
}
public override Type ComponentType
{
get { return typeof(Wrapper<T>); }
}
public override object GetValue(object component)
{
Wrapper<T> c = (Wrapper<T>)component;
return f(c.wrappee);
}
public override bool IsReadOnly
{
get { return true; }
}
public override Type PropertyType
{
get { return typeof(String); }
}
public override void ResetValue(object component)
{
throw new NotImplementedException();
}
public override void SetValue(object component, object value)
{
throw new NotImplementedException();
}
public override bool ShouldSerializeValue(object component)
{
return false;
}
}
}
可以这样使用:
List<DataClass> list = new List<DataClass>();
list.Add(new DataClass());
Dictionary<string, Func<DataClass, String>> ext = new Dictionary<string, Func<DataClass, string>>();
ext["New Column"] = (DataClass x) => String.Join(" ,", x.Items.ToArray());
List<Wrapper<DataClass>> list2 = new List<Wrapper<DataClass>>(list.Select(x=>new Wrapper<DataClass>(x,ext)));
class1DataGridView.DataSource = list2;
添加列后,在DataBindingComplete事件中执行如下操作:
foreach (DataGridViewRow row in dgv.Rows)
{if (row.Cells[7].Value.ToString()=="1")
row.Cells[0].Value = "number one"; }
(只是一个愚蠢的例子来说明)
,但记住它必须在DataBindingComplete(或从一个按钮点击等),否则它将保持空白