Search code examples
asp.netupdatepanel

Make any button on the page as a trigger for an asp.net UpdatePanel other than its sibling or child postback controls


Consider the following code fragment:

<div>
    <asp:Button runat="server" ID="trickyUPTrigger" Text="Tricky Update" />
    <div>
        <asp:Button runat="server" ID="normalUPTrigger" OnClick="normalUPTrigger_Click" Text="Normal Update" />
        <asp:UpdatePanel runat="server">
            <Triggers>
                <asp:AsyncPostBackTrigger ControlID="normalUPTrigger" />
            </Triggers>
            <ContentTemplate>
                <asp:Label runat="server" ID="changeableLabel" Text="Change me"></asp:Label>
            </ContentTemplate>
        </asp:UpdatePanel>
    </div>
</div>

Now make the button with ID of trickyUPTrigger as the trigger of the UpdatePanel. Or, devise a mechanism (probably... using javascript?) so that when this button is clicked UpdatePanel updates without full page postback.


Solution

  • If you want to update the UpdatePanel when clicking on trickyUPTrigger, you can add that button to the triggers list:

    <asp:UpdatePanel runat="server">
        <Triggers>
            <asp:AsyncPostBackTrigger ControlID="normalUPTrigger" EventName="Click" />
            <asp:AsyncPostBackTrigger ControlID="trickyUPTrigger" EventName="Click" />
        </Triggers>
        <ContentTemplate>
        ...
        </ContentTemplate>
    </asp:UpdatePanel>
    


    UPDATE

    You asked some code examples showing cases with naming containers, a concept that comes into play for databound controls with item templates, like the GridView and the ListView, and for user controls. In the examples below, I use a ListView, where each item is a separate naming container.

    If you wanted to trigger an update of your panel from a button in a ListView item template, the trigger would not be found at runtime, and an exception would occur:

    <asp:ListView ID="lstView" runat="server">
        <ItemTemplate>
            <asp:Button ID="anotherTrigger" runat="server" Text="This trigger cannot be found!" OnClick="anotherTrigger_Click" />
        </ItemTemplate>
    </asp:ListView>
    <asp:UpdatePanel runat="server">
        <Triggers>
            <asp:AsyncPostBackTrigger ControlID="anotherTrigger" EventName="Click" />
        </Triggers>
    </asp:UpdatePanel>
    

    The reverse case (the UpdatePanel in the ListView item template, the trigger button outside of the ListView) does work, according to my tests, which seems to contradict the note that you mention in your comment:

    <asp:ListView ID="lstView" runat="server">
        <ItemTemplate>
            <asp:UpdatePanel runat="server">
                <Triggers>
                    <asp:AsyncPostBackTrigger ControlID="anotherTrigger" EventName="Click" />
                </Triggers>
            </asp:UpdatePanel>
        </ItemTemplate>
    </asp:ListView>
    <asp:Button ID="anotherTrigger" runat="server" Text="This trigger works!" OnClick="anotherTrigger_Click" />
    

    Finally, the case where the UpdatePanel and the trigger button are both in the ListView item template also works:

    <asp:ListView ID="lstView" runat="server">
        <ItemTemplate>
            <asp:Button ID="anotherTrigger" runat="server" Text="This trigger works!" OnClick="anotherTrigger_Click" />
            <asp:UpdatePanel runat="server" UpdateMode="Conditional">
                <Triggers>
                    <asp:AsyncPostBackTrigger ControlID="anotherTrigger" EventName="Click" />
                </Triggers>
            </asp:UpdatePanel>
        </ItemTemplate>
    </asp:ListView>
    

    You can notice that I set UpdateMode="Conditional" for the panel in this last example. With this setting, the panel is updated only by its own triggers. If the attribute is set to UpdateMode="Always", the panel is updated not only by his own triggers but also by the triggers of the other UpdatePanels in the page. The default value is UpdateMode="Always" (as in your code sample).