如何在DataGridView中填充自定义列单元格

时间:2011-11-20 15:10:34

标签: c# winforms

我设法在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;
}

如何将数据放入自定义列?

2 个答案:

答案 0 :(得分:0)

它应该那样工作......

你确定代码运行时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;

答案 1 :(得分:0)

添加列后,在DataBindingComplete事件中执行以下操作:

foreach (DataGridViewRow row in dgv.Rows)
{if (row.Cells[7].Value.ToString()=="1")
row.Cells[0].Value = "number one"; }

(只是一个愚蠢的例子来说明)

但请记住,我必须在DataBindingComplete (或点击按钮等),否则它将保持空白