views:

1570

answers:

3

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?

A: 

I don't think there's a built-in way of binding generic lists to the datagrid. However, you could fairly easily create a UserControl that inherits from datagrid, and override/overload the binding methods to accommodate generic lists. The basic approach to this would be to generate a DataTable from the generic list, and bind the generated DataTable to the base datagrid. This approach would be read-only, of course.

MusiGenesis
A: 

If you're using 3.5 or 2.0 you can use a BindingList.

John Ingle
+2  A: 

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();
    }
Chris Brandsma