Filling a Datagrid with dynamic Columns

后端 未结 4 1180
清歌不尽
清歌不尽 2020-12-12 20:40

I have an Datagrid which needs to get filled dynamicly.

The tablelayout is like:

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

4条回答
  •  再見小時候
    2020-12-12 21:06

    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:

    
        
            
            
        
    
    

    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 Custom { get; set; }
    
        public CustomUser() : base()
        {
            Custom = new Dictionary();
        }
    }
    

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

    void PopulateRows(User[] users, Dictionary[] 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[] {
        new Dictionary { 
            "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:

    
    

    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.

提交回复
热议问题