简体   繁体   中英

Multiple link button on same cell of gridview - click event is not firing - c#

I have created multiple linkbutton on same cell of gridview row. But it's click event is not firing. On click event, I have to get StudentID defined in RowDataBound of Gridview.

protected void gvStudent_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        //loop through the cell.
        for (int j = 1; j < e.Row.Cells.Count; j++)
        {
            string[] arrLinks = null;
            if (!string.IsNullOrEmpty(e.Row.Cells[j].Text.ToString()) && e.Row.Cells[j].Text.ToString() != "&nbsp;")
            {
                arrLinks = e.Row.Cells[j].Text.Split(',');//Rahul-3495,Meera-2323
            }
            if (arrLinks != null)
            {
                for (int i = 0; i < arrLinks.Length; i++)
                {
                    LinkButton btnLink = new LinkButton();
                    string StudentName= (arrLinks[i].Split('-').First()).ToString();//Rahul
                    string StudentID = (arrLinks[i].Split('-').Last()).ToString();//3495
                    btnLink.ID ="btn_" +  StudentID;
                    btnLink.Text = StudentName + "<br>";                                                     
                  //  btnLink.Click += new EventHandler(StudentButtonsclick);
                     btnLink.CommandName = "btnLink"; 
                    e.Row.Cells[j].Controls.Add(btnLink);
                } 
            }
        }
    }     
}
protected void gvStudent_RowCommand(sender s, GridViewCommandEventArgs e)
{
    if (e.CommandName == "btnLink")
    { }
}
 <asp:GridView ID="gvStudent" runat="server" AutoGenerateColumns="true"  
 CssClass="gridview_alter" 
 OnRowDataBound="gvStudent_RowDataBound" OnRowCommand="gvStudent_RowCommand">           
</asp:GridView>

I would recommend using CommandName and OnRowCommand event for GridView . Here is how you should do it:

protected void gvStudent_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        //loop through the cell.
        for (int j = 1; j < e.Row.Cells.Count; j++)
        {
            string[] arrLinks = null;
            if (!string.IsNullOrEmpty(e.Row.Cells[j].Text.ToString()) && e.Row.Cells[j].Text.ToString() != "&nbsp;")
            {
                arrLinks = e.Row.Cells[j].Text.Split(',');//Rahul-3495,Meera-2323
            }
            if (arrLinks != null)
            {
                for (int i = 0; i < arrLinks.Length; i++)
                {
                    LinkButton btnLink = new LinkButton();
                    string StudentName= (arrLinks[i].Split('-').First()).ToString();//Rahul
                    string StudentID = (arrLinks[i].Split('-').Last()).ToString();//3495
                    btnLink.ID = "btn_" + StudentID; // Good to concatenate a string instead just a number in the ID.
                    btnLink.Text = StudentName + "<br>";                                                     
                    btnLink.CommandName = "btnLink"; // Add a CommandName
                    e.Row.Cells[j].Controls.Add(btnLink);
                } 
            }
        }
    }     
}
protected void GridView1_RowCommand(sender s, GridViewCommandEventArgs e)
{
    if (e.CommandName == "btnLink")
    {
        // Link Button was clicked. 
        var linkButton = (LinkButton)sender;
        if (linkButton != null)
        {
            var studentId = linkButton.ID.Replace("btn_", ""); // Remove the concatenated string from the id.
            // Do stuff with the student id.
            // I would highly not recommend getting the id from a button element, as it could be modified using browser inspect elements. Instead use, GridView DataKeys.
        }
    }
}

You should add RowCommand event in your GridView as well to get it going. eg:

<asp:GridView runat="server" ID="GridView1" OnRowCommand="GridView1_RowCommand">
    <!-- Rest of the elements -->
</asp:GridView>

Ok, the problem is that controls that require events that are created "after" the page has been rendered cannot really be wired up. You would have to move the code to a earlier event. So you are free to add controls, but they will in "most" cases be rendered TOO LATE to have events attached. Thus when you click on the link button, nothing fires.

So there are two solutions I can think of that will work.

First, set the control to have aa post back URL, and include a parameter on that post back.

eg this:

Dim lnkBtn As New LinkButton
lnkBtn.Text = "<br/>L" & I
lnkBtn.ID = "cL" & I
lnkBtn.PostBackUrl = "~/GridTest.aspx?r=" & bv.RowIndex

If you put a PostbackUrl, then when you click on the button, the page will post back. However, the grid row events such as rowindex change, or row click event etc. will NOT fire. So, if you willing to have a parameter passed back to the same page as per above, then you can pass the 1-3 (or 1-N) values you have for each control.

Of course that means you now have a parameter on the web page URL (and users will see this). You of course simply pick up the parameter value on page load with the standard

        Request.QueryString["ID"] or whatever.

However, another way - which I think is better is to simple wire up a OnClickClick() event in js, and thus do this:

  I = 1 to N
  Dim lnkBtn As New LinkButton
  lnkBtn.Text = "<br/>L" & I
  lnkBtn.ID = "cL" & I
  lnkBtn.OnClientClick = "mycellclick(" & I & ");return false;"

Now in above note how I am passing "I" to the js routine. You would pass your 200, 300 or whatever value you want.

then you script will look like this:

<script>
    function mycellclick(e) {
        __doPostBack("MySelect", e);
    }
</script>

So above simply takes the value passed from the cell click (and linkbutn), and then does the postback with a dopostback. I used "MySelect", and you can give that any name you want.

Now, in the on-load event, you can simply go like this:

 If Request("__EVENTTARGET") = "MySelect" Then
    Dim mypassvalue As String = Request("__EVENTARGUMENT").ToString
    Debug.Print("row sel for MySelect = " & mypassvalue)
 End If

So, you are 100% correct - clicking on those controls does NOT fire server side event, and they are wired up too late for this to occur. so you can and often do say add some columns or controls to a gridview, but they are created and rendered TOO LATE for the events to be wired up (and thus they don't fire when clicked on).

But, you can add a postback to the lnkbutton, and you can also add a OnClickClick() event (JavaScript function call) and they will both work. I don't like parameters in the URL appearing when you click, so I think the js script call as per above works rather nice.

So while in the comments I noted (and suggested) that you have to set the CommandName="Select". This suggesting still holds true (without CommandName = select, then the rowindex will not fire. You can't use just ANY name - it MUST be select. However this ONLY works if the control is part of the grid and not added on the fly. As noted, it might be possible to move the grid event to "earlier" event (page initialize) but it going to be a challenge and will require you to re-organize the page. The most clean, and one that does not require parameters in the URL is adding that js OnClientClick() event. You can however set the controls postbackurl and along with a parameter in the URL, and that also can work well if you open to URL with parameters (I don't like them).

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