Windows Mobile / .Net Compact Framework – How to bind generic lists to datagrid

compact-frameworkdatagridwindows-mobile

I'm building a small vb app using the latest version of the .net compact framework. The datagrid control is a bit more limited than I'm used to.

I'm seeing lots of examples where I can bind the grid's datasource to a dataset/datatable. Is it possible to bind to a generic list? If so, how?

Best Answer

You can just add the list to the datasource, but then you need to do some more work to get the columns to look the way you want.

I do this all the time actually, but it is a little involved. Note that my example is using .net 3.5 and some of the C# 3.0 features to make it easier.

First, here are the extension methods I'm using:

    public static T SelectedItem<T>(this DataGrid ctrl)
    {
        var cell = ctrl.CurrentCell;

        var list = (IList<T>)ctrl.DataSource;

        if (list == null)
            return default(T);
        if (list.Count == 0)
            return default(T);

        return list[cell.RowNumber];
    }

    private static void AddColumn(this GridColumnStylesCollection list, string header, string columnName, int width)
    {
        list.Add(
            new DataGridTextBoxColumn
            {
                HeaderText = header,
                MappingName = columnName,
                Width = width
            });
        return;
    }

    public static void SetColumnStyles<T>(this DataGrid ctrl, T data, params ColumnStyle[] column) where T : class
    {
        var ts = new DataGridTableStyle();
        ts.MappingName = data.GetType().Name;

        for (int i = 0; i < column.Length; i++)
        {
            var style = column[i];
            ts.GridColumnStyles.AddColumn(style.Header, style.Column, style.Width);
        }

        ctrl.TableStyles.Clear();
        ctrl.TableStyles.Add(ts);
    }

And this little class:

public class ColumnStyle
{
    public string Header { get; private set; }
    public string Column { get; private set; }
    public int Width { get; private set; }

    public ColumnStyle(string header, string column, int width)
    {
        Header = header;
        Column = column;
        Width = width;
    }

    public ColumnStyle(string column, int width)
    {
        Column = column;
        Header = column;
        Width = width;
    }
}

That is the setup, here is the payoff: Taking a generic list, spesifying the column names, and their widths:

    public void LoadInventoryList(IList<InventoryItemSmall> list)
    {
        inventoryGrid.SuspendLayout();

        inventoryGrid.DataSource = list;
        inventoryGrid.SetColumnStyles(list, new[]
                                          {
                                              new ColumnStyle("Name", 170),
                                              new ColumnStyle("Size", 30),
                                              new ColumnStyle("Quantity", 30)
                                          });
        inventoryGrid.ResumeLayout();
    }