Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically change GridView item template

I have a fairly big asp.net website that use GridView bound to the same object in lots of places. I'm using an item template to customize each row. However to have the same template in all the pages I have to copy & paste the item template to each page. Obviously this is not the best solution. On top of this I want to be able to change the template used by the GridView, by changing some configuration file. One option would be to create an user control with the DataGrid and expose the necessary properties to be used in each page. However this does not fulfill the second requirement to be able do dynamically change the template. Basically I'm looking for a way to say to the GridView to use a template and be able to do this dynamically. Any idea would be helpful.

like image 708
Albert Avatar asked Jun 03 '09 11:06

Albert


1 Answers

Alright, so here is the 100% manually building up of templated fields example.

The first step in creating dynamic template columns is to create a class that implements the System.Web.UI.ITemplate interface. For our simple example here, I am just going to use a label.

public class MyCustomTemplate : ITemplate
{
    public String DataField { get; set; }

    public MyCustomTemplate(String dataField)
    {
        DataField = dataField;
    }

    public void InstantiateIn(Control container)
    {
        var label = new Label();
        label.DataBinding += label_DataBinding;

        container.Controls.Add(label);
    }

    void label_DataBinding(object sender, EventArgs e)
    {
        var label = (Label)sender;
        var context = DataBinder.GetDataItem(label.NamingContainer);
        label.Text = DataBinder.Eval(context, DataField).ToString();
    }
}

Notice that in order to support DataBinding, you will have to manually handle that event on whatever control(s) you choose to add. Once you have developed your template, you can then use this as your ItemTemplate for any TemplateField that you want to use.

So, suppose that we have some collection of custom business objects that we want to bind our grid to.

public class MyCustomClass
{
    public String Name { get; set; }
    public Int32 Age { get; set; }
}

We are going to have to manually build up each column as a TemplateField, and then bind our collection to the GridView. In order to make this cleaner and easier to do, I have encapsulated the building up of the TemplateField collection into a static helper class:

public static class MyCustomTemplateCollection
{
    public static DataControlFieldCollection GetTemplateCollection()
    {
        var col = new DataControlFieldCollection();

        var nameField = new TemplateField
                        {
                            HeaderText = "Name",
                            ItemTemplate = new MyCustomTemplate("Name")
                        };

        var ageField = new TemplateField
                        {
                            HeaderText = "Age",
                            ItemTemplate = new MyCustomTemplate("Age")
                        };

        col.Add(nameField);
        col.Add(ageField);

        return col;
    }
}

Using this in your code behind would look something like this:

protected void Page_Load(object sender, EventArgs e)
{
    var dataSource = new List<MyCustomClass>
                        {
                            new MyCustomClass{Name = "Josh", Age = 43},
                    new MyCustomClass{Name = "Bob", Age = 14},
                    new MyCustomClass{Name = "Ashley", Age = 32},
                        };

    DynamicGrid(dataSource);
}

private void DynamicGrid(List<MyCustomClass> dataSource)
{
    var col = MyCustomTemplateCollection.GetTemplateCollection();

    foreach (DataControlField field in col)
    {
        myGridView.Columns.Add(field);
    }

    myGridView.DataSource = dataSource;
    myGridView.DataBind();
}

In the end, this will produce an output that is identical to the dynamic user controls example, but as you can see, it is much more cumbersome. This is also a very simplistic example that doesn't include any CSS attributes, or multiple types of controls. You could do this, but it would be painful, and might make you want to quit programming all together. Go with the user control solution and make your life easier.

like image 192
Josh Avatar answered Nov 13 '22 04:11

Josh