简体   繁体   English

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

[英]How to populate custom column cells in DataGridView

I managed to add another column to the DGV, but now I'm having trouble populating the cells with values. 我设法在DGV中添加了另一列,但是现在在用值填充单元格时遇到了麻烦。

Here's what I have so far: 这是我到目前为止的内容:

// 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;
}

How do I put data into the custom column? 如何将数据放入自定义列?

after you add the column, in the DataBindingComplete event do something like this: 添加列之后,在DataBindingComplete事件中执行以下操作:

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

(just a stupid example to illustrate) (只是一个愚蠢的例子来说明)

but remember IT HAS to be in the DataBindingComplete (or from a button click etc.) otherwise it'll remain blank 但请记住,它必须位于DataBindingComplete中 (或通过单击按钮等),否则它将保持空白

it should work that way ... 它应该以这种方式工作...

are you sure the DGV already has rows when your code runs? 您确定在代码运行时DGV已经有行吗?

but there is another thing you could think about: 但是您还可以考虑另一件事:

you could create wrappers for your data objects, and/or add a custom typedescriptor, to add a new property to your data that can be used by the .net databinding so you won't have to manually setup the columns ... 您可以为数据对象创建包装器,和/或添加自定义typedescriptor,以向数据添加新属性,以供.net数据绑定使用,因此您不必手动设置列...

something like this: 像这样的东西:

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

which then could be used like this: 然后可以这样使用:

    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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM