C# 如何将数据表数据绑定到自定义对象列表

C# 如何将数据表数据绑定到自定义对象列表,c#,data-binding,datatable,C#,Data Binding,Datatable,我有一个包含任务的类: class Task{ public string Description; public DateTime StartDate; public DateTime EndDate; } 我有一个SQLite数据库,它有一个名为“Task”的DataTable: 我可以创建从数据表填充的列表吗 我可以在列表中添加一个新的任务,并让它更新数据表吗 我可以创建从DataTable填充的列表吗 您需要这样的代码来完成所需的工作: // Creates IEnumer

我有一个包含任务的类:

class Task{
  public string Description;
  public DateTime StartDate;
  public DateTime EndDate;
}
我有一个SQLite数据库,它有一个名为“Task”的
DataTable

我可以创建从数据表填充的
列表吗

我可以在
列表中添加一个新的
任务
,并让它更新数据表吗

我可以创建从DataTable填充的列表吗

您需要这样的代码来完成所需的工作:

// Creates IEnumerable<DataRow>

var taskDataTableEnumerable = taskDataTable.AsEnumerable();

List<Task> myTaskList =
    (from item in taskDataTableEnumerable
     select new Task{
         Description = item.Field<string>("DescriptionColumnName"),
         StartDate = item.Field<DateTime>("StartDateColumnName"),
         EndDate = item.Field<DateTime>("EndDateColumnName")
    }).ToList();
  • 使用以下代码从新添加的任务对象向taskDataRow添加数据:

           taskDataRow["DescriptionColumnName"] = taskObject.Description
           taskDataRow["StartDateColumnName"] = taskObject.StartDate
           taskDataRow["EndDateColumnName"] = taskObject.EndDate
    
  • 这样,新添加到列表中的
    任务
    对象也会作为
    数据行
    添加到
    数据表
    ,以防
    FastMember
    不适用于您的用例,并且您需要一个不同的选项,然后可能计划使用下面这样的自定义代码,如果所有的
    类型T
    属性都将转换为具有适当列名的
    数据表
    ,您可以根据需要为字段添加选项,目前它用于属性:

        public static DataTable CreateTable<TDataTable>(this IEnumerable<TDataTable> collection)
        {
            // Fetch the type of List contained in the ParamValue
            var tableType = typeof(TDataTable);
    
            // Create DataTable which will contain data from List<T>
            var dataTable = new DataTable();
    
            // Fetch the Type fields count
            var columnCount = tableType.GetProperties().Count();
    
            var columnNameMappingDictionary = new Dictionary<string, string>();
    
            // Create DataTable Columns using table type field name and their types
            // Traversing through Column Collection
            for (var counter = 0; counter < columnCount; counter++)
            {
                var propertyInfo = tableType.GetProperties()[counter];                
    
                // Fetch DataParam attribute
                var dataParameterAttribute = propertyInfo.GetDataParameterAttribute();
    
                // Datatable column name based on DataParam attribute
                var columnName = (dataParameterAttribute != null) ? dataParameterAttribute.Name : propertyInfo.Name;
    
                columnNameMappingDictionary.Add(propertyInfo.Name,
                    (dataParameterAttribute != null) ? dataParameterAttribute.Name : propertyInfo.Name);
    
                // Fetch the current type of a property and check whether its nullable type before adding a column
                var currentType = tableType.GetProperties()[counter].PropertyType;
    
                dataTable.Columns.Add(columnName, Nullable.GetUnderlyingType(currentType) ?? currentType);
            }
    
            // Return parameter with null value
            if (collection == null)
                return dataTable;
    
            // Traverse through number of entries / rows in the List
            foreach (var item in collection)
            {
                // Create a new DataRow
                var dataRow = dataTable.NewRow();
    
                foreach (var columnName in columnNameMappingDictionary.Select(propertyinfo => propertyinfo.Value))
                {
                    dataRow[columnName] = item.GetType().GetProperty(columnName).GetValue(item) ?? DBNull.Value;
                }
                // Add Row to Table
                dataTable.Rows.Add(dataRow);
            }
    
            return (dataTable);
        }
    

    您可以将实体框架与SQLite数据库结合使用,我不知道什么是“开箱即用”的,但是有很多其他人编写的扩展方法可以做到这一点。例如:如果这个问题的上一个版本中有一个DB,那么为什么要创建任务对象呢?数据行可以表示一个
    任务
    ,您只需添加一行即可创建一个新的任务。任务对象将提供自动完成/提示,它还允许我使用任务对象内部的其他字段来完成DataGridView条目的不同区域,而无需进行大量转换。
           taskDataRow["DescriptionColumnName"] = taskObject.Description
           taskDataRow["StartDateColumnName"] = taskObject.StartDate
           taskDataRow["EndDateColumnName"] = taskObject.EndDate
    
        public static DataTable CreateTable<TDataTable>(this IEnumerable<TDataTable> collection)
        {
            // Fetch the type of List contained in the ParamValue
            var tableType = typeof(TDataTable);
    
            // Create DataTable which will contain data from List<T>
            var dataTable = new DataTable();
    
            // Fetch the Type fields count
            var columnCount = tableType.GetProperties().Count();
    
            var columnNameMappingDictionary = new Dictionary<string, string>();
    
            // Create DataTable Columns using table type field name and their types
            // Traversing through Column Collection
            for (var counter = 0; counter < columnCount; counter++)
            {
                var propertyInfo = tableType.GetProperties()[counter];                
    
                // Fetch DataParam attribute
                var dataParameterAttribute = propertyInfo.GetDataParameterAttribute();
    
                // Datatable column name based on DataParam attribute
                var columnName = (dataParameterAttribute != null) ? dataParameterAttribute.Name : propertyInfo.Name;
    
                columnNameMappingDictionary.Add(propertyInfo.Name,
                    (dataParameterAttribute != null) ? dataParameterAttribute.Name : propertyInfo.Name);
    
                // Fetch the current type of a property and check whether its nullable type before adding a column
                var currentType = tableType.GetProperties()[counter].PropertyType;
    
                dataTable.Columns.Add(columnName, Nullable.GetUnderlyingType(currentType) ?? currentType);
            }
    
            // Return parameter with null value
            if (collection == null)
                return dataTable;
    
            // Traverse through number of entries / rows in the List
            foreach (var item in collection)
            {
                // Create a new DataRow
                var dataRow = dataTable.NewRow();
    
                foreach (var columnName in columnNameMappingDictionary.Select(propertyinfo => propertyinfo.Value))
                {
                    dataRow[columnName] = item.GetType().GetProperty(columnName).GetValue(item) ?? DBNull.Value;
                }
                // Add Row to Table
                dataTable.Rows.Add(dataRow);
            }
    
            return (dataTable);
        }
    
    [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
        public class DataParamAttribute : Attribute
        {
            /// <summary>
            /// Gets or sets the name.
            /// </summary>
            public string Name { get; set; }
    
            /// <summary>
            /// Initializes a new instance of the <see cref="DataParamAttribute"/> class.
            /// </summary>
            /// <param name="name">
            /// The name.
            /// </param>
            public DataParamAttribute(string name)
            {
                this.Name = name;
            }
        }
    
    public static DataParamAttribute GetDataParameterAttribute(this PropertyInfo propertyInfo)
            {
                DataParamAttribute mappedAttribute = null;
    
                // Get list of Custom Attributes on a property
                var attributeArray = propertyInfo.GetCustomAttributes(false);
    
                // Column mapping of the ParameterAttribute
                var columnMapping =
                    attributeArray.FirstOrDefault(attribute => attribute.GetType() == typeof(DataParamAttribute));
    
                if (columnMapping != null)
                {
                    // Typecast to get the mapped attribute
                    mappedAttribute = columnMapping as DataParamAttribute;
                }
                return mappedAttribute;
            }