用动态列填充Datagrid [英] Filling a Datagrid with dynamic Columns

查看:144
本文介绍了用动态列填充Datagrid的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Datagrid需要动态填充。



表格如下:

  id |图像|名称|说明| Name-1 |名称N 

前4列是静态的,其他列是动态的。用户应该可以添加任意数量的用户。



我尝试通过在表中将它们相互放在一起来比较多个用户的数据。



现在我有一个列表框,它包含动态生成列的名称和填充静态列的方法。我也可以加载每个用户的数据。现在我需要将它们合并到一个大表中。



主要问题现在是:如何将Userdata和静态内容放在一个datagrid中。 >

解决方案

至少有三种方法:


  1. 从代码隐藏手动修改DataGrid的列

  2. 使用DataTable作为ItemsSource *

  3. 使用CustomTypeDescriptor

    *推荐简单







第一种方法:使用代码隐藏在运行时生成DataGrid的列。这实现起来很简单,但也可能感觉有点黑客,特别是如果你使用MVVM。所以你可以使用固定列的DataGrid:

 < DataGrid x:Name =grid> 
< DataGrid.Columns>
< DataGridTextColumn Binding ={Binding id}Header =id/>
< DataGridTextColumn Binding ={Binding image}Header =image/>
< /DataGrid.Columns>
< / DataGrid>

当您的名称准备就绪时,通过添加/删除列来修改网格,例如:

  //向数据网格添加新列
void AddColumns(string [] newColumnNames)
{
foreach(newColumnNames中的字符串名称)
{
grid.Columns.Add(new DataGridTextColumn {
//绑定到一个字典属性
Binding = new Binding(自定义[+名称+]),
标题=名称
});
}
}

你将要创建一个包装类,应该包含原始类,加上一个字典来包含自定义属性。假设你的主排类是User,那么你会想要一个这样的包装类:

  public class CustomUser :user 
{
public Dictionary< string,object>自定义{get;组;

public CustomUser():base()
{
Custom = new Dictionary< string,object>();
}
}

填充 ItemsSource 这个新的CustomUser类的集合:

  void PopulateRows(User [] users,Dictionary< string,object> [] customProps)
{
var customUsers = users.Select((user,index)=> new CustomUser {
Custom = customProps [index];
});
grid.ItemsSource = customUsers;
}

所以把它绑在一起,例如:

  var newColumnNames = new string [] {Name1,Name2}; 
var users = new User [] {new User {id =First User}};
var newProps = new Dictionary< string,object> [] {
new Dictionary< string,object> {
Name1,First User of First User,
Name2,Second Name of First User,
},
};
AddColumns(newColumnNames);
PopulateRows(users,newProps);






第二种方式:使用 DataTable 。这使得使用定制类型的基础设施,但更容易使用。只需将DataGrid的 ItemsSource 绑定到一个 DataTable.DefaultView 属性:

 < DataGrid ItemsSource ={Binding Data.DefaultView}AutoGenerateColumns =True/> 

然后,您可以自定义列,例如:

  Data = new DataTable(); 

//创建固定列
Data.Columns.Add(id);
Data.Columns.Add(image);

//创建自定义列
Data.Columns.Add(Name1);
Data.Columns.Add(Name2);

//添加一行作为对象数组
Data.Rows.Add(new object [] {123,image.png,Foo,Bar});






第三种方法:利用.Net类型系统的可扩展性。具体来说,使用 CustomTypeDescriptor 。这允许您在运行时创建自定义类型;这又使您能够告诉DataGrid您的类型具有属性Name1,Name2,...NameN或任何其他您想要的。有关此方法的简单示例,请参阅此处


I have an Datagrid which needs to get filled dynamicly.

The tablelayout is like:

id | image | name | Description | Name-1 | Name-N

The first 4 columns are static the others are dynamic. The User should be able to add as many users as he wants.

I try to compare data of multiple users by putting them next to each other in the table.

Right now I have an Listbox whitch containes the Names of the dynamic generated Columns and an method that filles the static columns. I also can load the datas for each User. now I need to merge them to one big Table.

The main Problem is now: How to put the "Userdata" and the static content in one datagrid.

解决方案

There are at least three ways of doing this:

  1. Modify the DataGrid's columns manually from code-behind
  2. Use a DataTable as the ItemsSource *
  3. Use a CustomTypeDescriptor

    *recommended for simplicity


1st approach: use code-behind to generate the DataGrid's columns at runtime. This is simple to implement, but maybe feels a bit hackish, especially if you're using MVVM. So you'd have your DataGrid with fixed columns:

<DataGrid x:Name="grid">
    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding id}" Header="id" />
        <DataGridTextColumn Binding="{Binding image}" Header="image" />
    </DataGrid.Columns>
</DataGrid>

When you have your "Names" ready, then modify the grid by adding/removing columns, eg:

// add new columns to the data grid
void AddColumns(string[] newColumnNames)
{
    foreach (string name in newColumnNames)
    {
        grid.Columns.Add(new DataGridTextColumn { 
            // bind to a dictionary property
            Binding = new Binding("Custom[" + name + "]"), 
            Header = name 
        });
    }
}

You'll want to create a wrapper class, which should contain the original class, plus a dictionary to contain the custom properties. Let's say your main row class is "User", then you'd want a wrapper class something like this:

public class CustomUser : User
{
    public Dictionary<string, object> Custom { get; set; }

    public CustomUser() : base()
    {
        Custom = new Dictionary<string, object>();
    }
}

Populate the ItemsSource with a collection of this new "CustomUser" class:

void PopulateRows(User[] users, Dictionary<string, object>[] customProps)
{
    var customUsers = users.Select((user, index) => new CustomUser {
        Custom = customProps[index];
    });
    grid.ItemsSource = customUsers;
}

So tying it together, for example:

var newColumnNames = new string[] { "Name1", "Name2" };
var users = new User[] { new User { id="First User" } };
var newProps = new Dictionary<string, object>[] {
    new Dictionary<string, object> { 
        "Name1", "First Name of First User",
        "Name2", "Second Name of First User",
    },
};
AddColumns(newColumnNames);
PopulateRows(users, newProps);


2nd approach: use a DataTable. This makes use of the custom-type infrastructure under the hood, but is easier to use. Just bind the DataGrid's ItemsSource to a DataTable.DefaultView property:

<DataGrid ItemsSource="{Binding Data.DefaultView}" AutoGenerateColumns="True" />

Then you can define the columns however you like, eg:

Data = new DataTable();

// create "fixed" columns
Data.Columns.Add("id");
Data.Columns.Add("image");

// create custom columns
Data.Columns.Add("Name1");
Data.Columns.Add("Name2");

// add one row as an object array
Data.Rows.Add(new object[] { 123, "image.png", "Foo", "Bar" });


3rd approach: make use of the extensibility of .Net's type system. Specifically, use a CustomTypeDescriptor. This allows you to create a custom type at runtime; which in turn enables you to tell the DataGrid that your type has the properties "Name1", "Name2", ... "NameN", or whatever others you want. See here for a simple example of this approach.

这篇关于用动态列填充Datagrid的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆