Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LinkButton command event seems to not be firing

Tags:

asp.net

I created a simple user control using the AJAX Control Toolkit Accordion, LinkButton, and TextBox like this:

TestControl.ascx:

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="TestControl.ascx.cs" Inherits="TestControl" %>
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc1" %>
<cc1:Accordion ID="Accordion1" runat="server">
    <Panes></Panes>
    <HeaderTemplate>
        <div><%# Container.DataItem %></div>
    </HeaderTemplate>
    <ContentTemplate>
        <div>
            <asp:TextBox ID="textBox" Text='<%# Container.DataItem %>' runat="server"></asp:TextBox>
            <asp:LinkButton Text="Update" CommandName="Update" CommandArgument='<%# Container.DataItem %>' OnCommand="LinkButton_Command" runat="server"></asp:LinkButton>
        </div>
    </ContentTemplate>
</cc1:Accordion>

And TestControl.ascx.cx:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class TestControl : System.Web.UI.UserControl
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Accordion1.DataSource = new string[] { "one", "two", "three" };
        Accordion1.DataBind();
    }

    protected void LinkButton_Command(object sender, CommandEventArgs e)
    {
        if (e.CommandName == "Update")
        {
            TextBox value = ((LinkButton)sender).Parent.FindControl("textBox") as TextBox;
            ((string[])Accordion1.DataSource)[Accordion1.SelectedIndex] = value.Text;
            Accordion1.DataBind();
        }
    }
}

The LinkButton_Command event handler doesn't fire at all on the first click, but on the second. Is there a problem with where the lifecycle the controls are being created that causes events not to be hooked up properly?

Update: I'm adding the control statically:

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>

<%@ Register src="TestControl.ascx" tagname="TestControl" tagprefix="uc2" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>

    <form id="form1" runat="server">    
    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>
    <div border="1">
        <uc2:TestControl ID="TestControl1" runat="server" />
    </div>



    </form>
</body>
</html>
like image 344
Ben Collins Avatar asked Apr 09 '09 20:04

Ben Collins


1 Answers

Here's a solution. I checked this out in a test project, and this works:

ASCX:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="TestControl.ascx.cs" Inherits="WebApplication1.TestControl" %>
<%@ Import Namespace="System.ComponentModel"%>
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc1" %>

<cc1:Accordion ID="Accordion1" runat="server" Enabled="True">

    <Panes></Panes>
    <HeaderTemplate>
        <div><asp:Label runat="server" ID="HeaderLabel"><%# Container.DataItem %></asp:Label></div>
    </HeaderTemplate>
    <ContentTemplate>
        <div>
            <asp:TextBox ID="textBox" Text='<%# Container.DataItem %>' runat="server"></asp:TextBox>
            <asp:LinkButton ID="LinkButton1" Text="Update" CommandName="Update" CommandArgument='<%# Container.DataItem %>' 
            OnCommand="LinkButton_Command" runat="server"></asp:LinkButton>
        </div>
    </ContentTemplate>

</cc1:Accordion>

Codebehind:

public partial class TestControl : System.Web.UI.UserControl
{
    protected void Page_Init(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            Accordion1.DataSource = new string[] {"one", "two", "three"};
            Accordion1.DataBind();
        }
    }

    protected void LinkButton_Command(object sender, CommandEventArgs e)
    {
        if (e.CommandName == "Update")
        {
            TextBox value = ((LinkButton)sender).Parent.FindControl("textBox") as TextBox;
            (Accordion1.Panes[Accordion1.SelectedIndex].Controls[0].Controls[1] as Label).Text = value.Text;
        }
    }
}

It appears that Databinding the Accordion has some issues that mess up your event handlers getting wired up. Re-binding it every time nukes them somehow.

Also, your posted code has a DataBind() being called in the LinkButton_Command method, which is occurring after viewstate has been loaded. This would lead to the updated data not being shown until the next postback, because the new bindings wouldn't be saved in ViewState. It would act like it was always one postback behind.

like image 147
womp Avatar answered Nov 02 '22 10:11

womp