Repeater and add columns to header and itemtemplate on page load

19,171

Use nested Repeaters: the outer Repeater is for rows and has a HeaderTemplate and ItemTemplate which contain inner Repeaters for header and checkbox columns respectively. Something like this:

<asp:Repeater runat="server" ID="rowRepeater" OnItemDataBound="rowRepeater_ItemBound">
    <HeaderTemplate>
        <table>                                
        <tr>
            <asp:Repeater runat="server" ID="headerRepeater">
                <ItemTemplate>
                    <th>
                        <%# Container.DataItem %>
                    </th>
                </ItemTemplate>
            </asp:Repeater>
        </tr>
    </HeaderTemplate>
    <ItemTemplate>
        <tr>
            <td><asp:Label runat="server" ID="lblUserName" Text='<%# Eval("Key") %>' /></td>
            <asp:Repeater runat="server" ID="columnRepeater">
                <ItemTemplate>
                    <td>
                        <asp:HiddenField runat="server" ID="hfRoleIndex" Value='<%# Container.ItemIndex %>' />
                        <asp:CheckBox runat="server" ID="cbColumnValue" Checked='<%# Container.DataItem %>' OnCheckedChanged="cbColumnValue_CheckedChanged" AutoPostBack="true" />
                    </td>
                </ItemTemplate>
            </asp:Repeater>
        </tr>
    </ItemTemplate>
    <FooterTemplate>
        </table>
    </FooterTemplate>
</asp:Repeater>

and in your code behind:

Dictionary<string, bool[]> userRoles = new Dictionary<string, bool[]>(){
    {"Bob", new bool[]{true,true,false,false}},
    {"Tim",new bool[]{false,false,true,true}},
    {"John",new bool[]{false,true,false,true}}
};

string[] headings = { "Rep Name", "Caller", "Closer", "Manager", "SuperUser" };

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        rowRepeater.DataSource = userRoles;
        rowRepeater.DataBind();
    }
}

protected void rowRepeater_ItemBound(object sender, RepeaterItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.Header)
    {
        Repeater headerRepeater = e.Item.FindControl("headerRepeater") as Repeater;
        headerRepeater.DataSource = headings;
        headerRepeater.DataBind();
    }
    else if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
    {
        Repeater columnRepeater = e.Item.FindControl("columnRepeater") as Repeater;
        columnRepeater.DataSource = ((KeyValuePair<string, bool[]>)e.Item.DataItem).Value;
        columnRepeater.DataBind();
    }
}

protected void cbColumnValue_CheckedChanged(object sender, EventArgs e)
{
    CheckBox cb = sender as CheckBox;
    HiddenField hf = cb.Parent.FindControl("hfRoleIndex") as HiddenField;
    int roleIndex = int.Parse(hf.Value); // now you have the column identifier

    Label lbl = cb.Parent.Parent.Parent.FindControl("lblUserName") as Label;
    string userName = lbl.Text; //now you have the row identifier

    //now you can update your data source
    userRoles[userName][roleIndex] = cb.Checked;
}
Share:
19,171
sdmiller
Author by

sdmiller

Obsessive Software developer who relaxes by writing code. Something is wrong with me!

Updated on June 19, 2022

Comments

  • sdmiller
    sdmiller almost 2 years

    I haven't used repeaters for much more than showing data from a datatable.

    I am building a grid that that shows a list of users and columns of roles that the user has been assigned, shown with checkboxes (shown with true/false below but pretent they are checkboxes).

    ex.

    |Rep Name|Caller|Closer|Manager|SuperUser|
    |Bob           |True  |true   | false      | false |
    |Tom          |false  |false  |True       | True |

    Basically using it for roles management.

    However the roles may change later on so I want to load the roles(headers and items) dynamically into the repeater.

    I am not sure how to do this or if it is even possible.

    I figure you grab a list of current role possibilities and load them into the headertemplate but I am not sure how to match those with the itemtemplate and how to create checkboxes and place them in the itemtemplate.

    Sorry if it is a rudementary question.... I appreciate any advice!

    Datatable example of data that I am going to get... though I will also return ids for roles and users that are not shown here.

    DataTable dt = new DataTable(); DataColumn dc = new DataColumn();

          dc.DataType = Type.GetType("System.String");
          dc.ColumnName = "RepName";
          dt.Columns.Add(dc);
    
          dc = new DataColumn(); 
          dc.DataType = Type.GetType("System.Boolean");
          dc.ColumnName = "Caller";
          dt.Columns.Add(dc);
    
          dc = new DataColumn();
          dc.DataType = Type.GetType("System.Boolean");
          dc.ColumnName = "closer";
          dt.Columns.Add(dc);
    
          dc = new DataColumn();
          dc.DataType = Type.GetType("System.Boolean");
          dc.ColumnName = "Admin";
          dt.Columns.Add(dc);
    
          dc = new DataColumn();
          dc.DataType = Type.GetType("System.Boolean");
          dc.ColumnName = "SuperUser";
          dt.Columns.Add(dc);
    
    
          DataRow row;
    
          row = dt.NewRow();
    
          row["RepName"] = "Joe";
          row["Caller"] = true;
          row["closer"] = false;
          row["Admin"] = true;
          row["SuperUser"] = false;
          dt.Rows.Add(row);
    
          row = dt.NewRow();
    
          row["RepName"] = "Bob";
          row["Caller"] = true;
          row["closer"] = false;
          row["Admin"] = true;
          row["SuperUser"] = false;
          dt.Rows.Add(row);
    
    
          row = dt.NewRow();
    
          row["RepName"] = "Tom";
          row["Caller"] = true;
          row["closer"] = false;
          row["Admin"] = true;
          row["SuperUser"] = false;
          dt.Rows.Add(row);