简体   繁体   中英

How to change a View with a button on a Repeater?

I have the following structure

<asp:UpdatePanel ID="MyUpdatePanel" runat="server">
    <ContentTemplate>
        <asp:MultiView ID="MyViews" runat="server">
            <asp:View ID="List" runat="server">
                <asp:Repeater runat="server" ID="Repeater1">
                    <ItemTemplate>
                        <asp:LinkButton ID="Button1" runat="server" Text="Button1" CommandName="View" />
                    </ItemTemplate>
                </asp:Repeater>
            </asp:View>
            <asp:View ID="Single" runat="server">
                <asp:LinkButton ID="Button2" runat="server" Text="Button2" />
            </asp:View>
        </asp:MultiView>
    </ContentTemplate>
</asp:UpdatePanel>

On the code behind I get the repeater ItemDataBound event, get the control using var button1 = e.Item.FindControl("Button1") as LinkButton; then I assign a CommandArgument with the ID of the current element.

This is being executed immediately after the CreateChildControls method.

Repeater1.ItemDataBound += (s, e) =>
{
    if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
    {
        var Button1 = e.Item.FindControl("Button1") as LinkButton;
        Button1.CommandArgument = item.ID.ToString();
    }
};

Repeater1.ItemCommand += (s, e) =>
{
    if (e.CommandName == "View")
    {
        var item = provider.Get(Convert.ToInt64(e.CommandArgument));
        BuildSingleView(item);
    }
};

This method just change the view...

public void BuildSingleView(var item)
{
    MyViews.ActiveViewIndex = 1;
    /* Edit
       I've tried to call here
       Initialize(), EnsureChildControls(), CreateChildControls()
       but it was a useless try. I also tried to catch exceptions,
       but none happened.
     */
}

The problem is that the view doesn't change. When I click the LinkButton it executes the CreateChildControls and after it calls the event ItemCommand , the event calls the BuildSingleView , the ActiveViewIndex is changed but nothing happens on the page.

I don't understand why it doesn't change. Is it a problem with the order of events? What could I do to change the view when I click a LinkButton?


Here is the full code-behind code (the Initialize method is the method that executes immediately after CreateChildControls) http://pastebin.com/2qwrKNxf

And here the full ascx file http://pastebin.com/P8RSbY9U

How about using MultiView.SwitchViewByIndexCommandName value as CommandName to button?

Another way would be to set hidden field on page on button click and then checking value of hidden field to switch the active view.

You just need to do the below:

Repeater1.ItemDataBound += (s, e) =>
{
    if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
    {
        var Button1 = e.Item.FindControl("Button1") as LinkButton;
        Button1.CommandArgument = item.ID.ToString();
    }
};

before Repeater1.DataBind();

That will solve the problem, because ItemDataBound event will fired right after you call DataBind() method. If you add new handler to ItemDataBound event after Binding the Repeater, it will never be fired.

I mean,

Repeater1.DataSource = List;
Repeater1.DataBind();

Repeater1.ItemDataBound += (s, e) =>
{
    if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
    {
        var item = e.Item.DataItem as Person;
        var Button1 = e.Item.FindControl("Button1") as LinkButton;
    }
};

will not work, but:

Repeater1.ItemDataBound += (s, e) =>
{
    if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
    {
        var item = e.Item.DataItem as Person;
        var Button1 = e.Item.FindControl("Button1") as LinkButton;
    }
};

Repeater1.DataSource = List;
Repeater1.DataBind();

will work.

Just a thought... But why not just assign the ID as an Eval/Bind? (It's the same in VB.net asn C#... right? Below is how I would do it in VB)

<asp:LinkButton ID="Button1" runat="server" Text="Button1" CommandName="View" CommandArgument='<%# Eval("WhateverYourIDFieldIs")' />

I figured out that when the update panel posts back it doesn't call the event handler first. So in order to get it to execute I need to re-assign the event.

My problem was that the control wasn't saving the ViewState, so it kept creating the wrong events. I replaced the ViewState with a Session and I got the behavior I wanted.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM