如何在DataTable行

时间:2015-09-20 09:08:08

标签: c# .net datatable reference

如何将DataTable Row中的对象存储到几列,或者在一列中包含对象,在另一列中引用该对象的属性?

class MyDataTable : DataTable
{
    public MyDataTable
    {
        this.Columns.Add("col1");
        this.Columns.Add("col2")        
        this.Columns.Add("Cat", typeof(Cat))
        this.Columns.Add("CatType")

        Cat cat1 = new Cat("name1", "type1")
        Cat cat2 = new Cat("name2", "type2")
        this.Rows.add(new object[] {"value","value",cat1,cat1.type} )
        this.Rows.add(new object[] {"value","value",cat2,cat2.type} )

        // I want to show table like: 
        // |value|value|name1|type1|
        // |value|value|name2|type2|

        // while type should be a reference not a static string, so
        cat1.type = "type3"; //should be able to change table like:

        // |value|value|name1|type3|
        // |value|value|name2|type2|    
    }
} 

class Cat
{
    string name;
    string type;
    public Cat(...){..}

    public override string toString()
        return name;
}

或者也许是在桌上摆桌子?:

class MyDataTable : DataTable
{
    public MyDataTable
    {
        this.Columns.Add("col1");
        this.Columns.Add("col2")        
        this.Columns.Add("Cat", typeof(Cat))

        Cat cat1 = new Cat("name1", "type1")
        Cat cat2 = new Cat("name2", "type2")
        this.Rows.add(new object[] {"value","value",cat1} )
        this.Rows.add(new object[] {"value","value",cat2} )

        // And show table like: 
        // |value|value||name1|type1||
        // |value|value||name2|type2||
    }
} 

 class Cat : DataTable {
      public Cat(string name, string type){
        this.Columns.Add("name");
        this.Columns.Add("type");
        this.Rows.Add(name,type);
      } 
 }

但能够在:

中显示Cat列
 datagridview1.DataSource = new MyDataTable();

////

@rene答案

当我将'type'设置为LiveString时:

datagridview.datasource = new List<Cat>(...)

尝试编辑与此对象关联的datagridview GUI单元格,我得到:

System.FormatException: Invalid cast from 'System.String' to 'syb_con.LiveString'. ---> System.InvalidCastException: Invalid cast from 'System.String' to 'syb_con.LiveString'.

  at System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider)

   at System.String.System.IConvertible.ToType(Type type, IFormatProvider provider)

   at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)

   at System.Windows.Forms.Formatter.ChangeType(Object value, Type type, IFormatProvider formatInfo)

   --- End of inner exception stack trace ---

   at System.Windows.Forms.Formatter.ChangeType(Object value, Type type, IFormatProvider formatInfo)

   at System.Windows.Forms.Formatter.ParseObjectInternal(Object value, Type targetType, Type sourceType, TypeConverter targetConverter, TypeConverter sourceConverter, IFormatProvider formatInfo, Object formattedNullValue)

   at System.Windows.Forms.Formatter.ParseObject(Object value, Type targetType, Type sourceType, TypeConverter targetConverter, TypeConverter sourceConverter, IFormatProvider formatInfo, Object formattedNullValue, Object dataSourceNullValue)

   at System.Windows.Forms.DataGridViewCell.ParseFormattedValueInternal(Type valueType, Object formattedValue, DataGridViewCellStyle cellStyle, TypeConverter formattedValueTypeConverter, TypeConverter valueTypeConverter)

   at System.Windows.Forms.DataGridViewCell.ParseFormattedValue(Object formattedValue, DataGridViewCellStyle cellStyle, TypeConverter formattedValueTypeConverter, TypeConverter valueTypeConverter)

   at System.Windows.Forms.DataGridView.PushFormattedValue(DataGridViewCell& dataGridViewCurrentCell, Object formattedValue, Exception& exception)

1 个答案:

答案 0 :(得分:0)

DataTable的目的是在向行添加行时存储状态。您的用例似乎超出了其设计能力。

如果我们允许使用允许更改其值的类型替换Type属性的不可变类型字符串,则用于添加对象的技巧也可用于该类型。我们使用的事实是,对于Object类型的DataColumns,Row将在该对象上调用ToString

我将介绍一种名为LiveString

的新类型
class LiveString 
{
    string value;

    internal string Value {
        get{return value;}
        set{this.value= value;}
    }

    public LiveString(string value) {
       this.value = value;
    }

    // use an implicit operator
    public static implicit operator LiveString(string value)
    {
        return new LiveString(value);
    }

    public override string ToString() {
        return value;
    }
}

它的目标是包装一个字符串并拥有从字符串创建新对象的方法,但也可以获取并更改其内部状态。我使用了conversion operator,因此Cat类的当前用户不必更改其代码。

您必须按照以下方式调整代码:

class MyDataTable : DataTable
{
    public MyDataTable()
    {
        this.Columns.Add("col1");
        this.Columns.Add("col2");        
        this.Columns.Add("Cat", typeof(Cat));
        // notice the typeof here
        this.Columns.Add("CatType", typeof(LiveString));

        Cat cat1 = new Cat("name1", "type1");
        Cat cat2 = new Cat("name2", "type2");
        this.Rows.Add(new object[] {"value","value",cat1,cat1.type} );
        this.Rows.Add(new object[] {"value","value",cat2,cat2.type} );

        cat1.type = "type3"; 
    }
} 

你的猫班。请注意I类型的setter如何不替换_type上的当前对象,而只替换Value的{​​{1}}。这可以保证Row保存的实例得到更新,而不是替换为不在行中存储或更新的新实例。

class Cat
{
    string name;
    LiveString _type;
    public LiveString type {
        get 
        { 
            return _type;
        }
        set 
        {
            _type.Value = value.Value;
        }
    }

    public Cat(string name, string type){this.name= name; this._type = type;}

    public override string ToString()
    {
        return name;
    }
}

此示例尝试尽可能接近使用DataTable。您可以使用元数据来构建您自己的集合,该元数据包含它所拥有的类型以及您希望如何表示它们。我认为lambda expressions在该实现空间中非常有用。其他选项可能是使用reflection