views:

58

answers:

1

I have a nested Repeater control in the ItemTemplate of another Repeater. I want to dynamically add a delete and update button to certain items in the nested Repeater depending on their data value, in this case whether they're associated with the current user. A click to either button should handled server-side based so the data source can be updated, the nested repeater re-bound and an Update Panel that contains both repeaters would be updated.

<asp:Repeater ID="rpProCom" runat="server">
    <HeaderTemplate><div class="comment"></HeaderTemplate>
    <ItemTemplate>
        <div class="c-score"><%# Eval("Text") %></div>
        <asp:UpdatePanel ID="upOut" runat="server" ChildrenAsTriggers="true" UpdateMode="Always" >
        <ContentTemplate>
        <asp:Repeater ID="rpVotes" runat="server" DataSource='<%# ((ScoreBoard.Score)Container.DataItem).Votes %>' OnItemDataBound="rpVotes_ItemDataBound">
            <HeaderTemplate><ul></HeaderTemplate>
            <ItemTemplate>
            <li>
            <div class="c-ctrl"><asp:PlaceHolder ID="phD" runat="server" /></div>
            <div class="c-box"><!-- placeholder for more tools --></div>
            <div class="c-i"><div runat="server" ID="imgCom" class='<%# Eval("ImgClass") %>' /></div>
            <div class="c-head">
                <strong><%# Eval("UserName") %></strong>
                <br /><%# Eval("Dt")%>
            </div>
            <div class="c-body"><%# Eval("Comment") %></div>
            </li></ItemTemplate><FooterTemplate></ul></FooterTemplate>
        </asp:Repeater>
        </ContentTemplate></asp:UpdatePanel>
    </ItemTemplate> 
    <FooterTemplate></div></FooterTemplate>
</asp:Repeater>

The outer repeater is bound in Page_Init

protected void rpVotes_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) {
    if (((Vote)e.Item.DataItem).UserName == user.UserName){
        LinkButton btn = new LinkButton();
        btn.Text = "delete";
        btn.CommandName = "delCom";
        btn.CommandArgument = ((Vote)e.Item.DataItem).ID.ToString();
        btn.Click += new EventHandler(DeleteComment);
        btn.ID = "d" + ((Vote)e.Item.DataItem).ID.ToString();
        //find contrl
        e.Item.FindControl("phD").Controls.Add(btn);
    }
    }
}

Since the Button is created on item databound and is nested within another control, I can't think of a reasonable way to persist the button and the unique identifier of the Data Item in Viewstate so I can recreate the button(s) on PageInit postback in order to fire the button's Click event.

I tried using Command Arguments, but they are empty:

javascript:__doPostBack('ctl00$CPHRight$rpProCom$ctl02$rpVotes$ctl01$d21','')

I need a reference to the containing Repeater and a unique identifier for the item in the repeater so I can update the DB and rebind that Repeater (ideally in an UpdatePanel that encompasses just that Repeater). I know this is a classic problem, and I'm sure someone's solved it.

So basically, is there some way to force a command argument into a dynamically control created dynamically during ItemDataBound or otherwise identify which dynamically created button caused postback? Can I put and Update Panel in a Repeater? Also can I possibly use the word dynamically again in this post?

A: 

Hey,

You can use dynamically as much as you want :-)

What I would recommend is declaring a static button, adding an itemdatabound event, and showing/hiding the button instead by setting the Visible property of it; that way, you won't have to concern yourself with the reloading issues, but the user won't be able to see the buttons they don't have permissions for.

HTH.

Brian
I was thinking the same thing, but there could be hundreds of items in the repeater and only about 5-10% of the items need a button. Adding to all of them would cause bloat in the ViewState that I'd like to avoid if possible. It's a great suggestion though.
Laramie
The converse, adding a dynamic button, might be a nightmare to maintain if you have a lot of items like that.
Brian
After weighing the options, I went ahead and took the hit. Too bad there's no way (that I can think of) to disable the ViewState then selectively enable it in DataBinding. I guess it's just the nature of the page life-cycle. Thanks for the sounding board.
Laramie
Well you can disable viewstate and bind on every page load... that is always an option, but that can be a lot of hits against the database.
Brian