I have a gridview looks like below.
Name Attended_Exam
Raj English
Hindi
Das Korea
Rahul Spanish
English
And the query used to bind datatable to this gridview contains a submission_id. Which is unique for each student and his subject.
Each attended exam name is shown as a linkbutton. Now, when clicking on it, I want to get the Submission_id of each subject. What is the best way to achieve this?
<asp:GridView ID="gvSubmissionHeaders" runat="server" AutoGenerateColumns="true"
Width="80%" OnRowDataBound="gvSubmissionHeaders_RowDataBound"
Font-Bold="false" RowStyle-Height="30px" >
</asp:GridView>
protected void gvSubmissionHeaders_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{ //for adding linkbutton to Attended_Exam
//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()!= " ")
{
arrLinks = e.Row.Cells[j].Text.Split(',');
}
if(arrLinks!=null)
{
for (int i = 0; i < arrLinks.Length; i++)
{
LinkButton btnLink = new LinkButton();
btnLink.ID = "Id" + arrLinks[i] + i;
btnLink.Text = arrLinks[i] + "<br>";
e.Row.Cells[j].Controls.Add(btnLink);
}
}
}
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
Ok, the detail here is that you could have simply noted that you have cell/colum in the grid, and you might add 1 or maybe 4 link buttons into that cell. So you have “N” buttons that you add, and you need/want particular information from that button.
If the button was static (a single link button), then you can add custom attributes to that button, and even additional columns data (ones not displayed in the grid) like this:
<td align="center" >
<asp:LinkButton ID="pUploadFiles" runat="server"
CommandArgument='<%# Eval("ID")%>' CommandName='cmdView'
Width="120px" align="center"
ContactNameID = '<%# Eval("ContactNameID")%>'
QuoteNum = '<%# Eval("QuoteNum")%>'
ProjectHeaderID = '<%# Eval("ID")%>'
>
</asp:LinkButton>
</td>
So now when you get the sender, or do a findcontrol, you can do this in code:
Dim btn As LinkButton ' we get required data from btn on row.
btn = lvd.FindControl("pUploadFiles")
With btn.Attributes
Session("ContactID") = .Item("ContactNameID")
Session("ContactGeneralID") = .Item("ContactGeneralID")
Session("QuoteNum") = .Item("QuoteNum")
End With
So linkbtn.Attributes.Item(“my custom value”) will get you any extra values (columns) that you attached to that link button. And with the above eval(), you can even pull any column from the data source as long as those column exist in the datatable/datasource that drives the listview or gridview. (the great part here is that you don’t need actual columns in the gridview/listview to try and store and “hide” these values. The extra values are simply part of that given control as custom attributes.
Now you are adding the link btn in code, but you can do the same thing.
eg:
LinkButton btnLink = new LinkButton();
btnLink.ID = "Id" + arrLinks[i] + i;
btnLink.Text = arrLinks[i] + "<br>";
btnLink.Attributes.Add("Submission_id","100");
e.Row.Cells[j].Controls.Add(btnLink);
Now of course you would replace the hard coded “100” in above with the value you are pulling or want to store as a custom attribute. So you can add 1 or “many” custom attributes to that link button. When the click on that link button, then you grab/get the additional attributes that are associated with that link button by using Mybtn.Attributes.Item(“Submission_id”).
So be it one link button that is part of the grid, you can add those extra attributes (without even extra code), and even rows from the databind that are not in the grid.
So I can have several buttons, and when they click, then additional information such as PK row, or even several other values can be part of (or added) to that one button. And in your case this should work fine if you dynamic adding 1 or 5 buttons as you are. So, those additonal values you want can simply become additonal attributes of that button.
Edit:
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 a a 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).
Method 2
First you declare your table column ID on the DataKeyNames on GridView eg:
<asp:GridView DataKeyNames="cTableColumnID" ID="gvSubmissionHeaders" runat="server" ...
Then you can get this ID per Row using this line
gvSubmissionHeaders.DataKeys[CurrectRowNum]["cTableColumnID"]
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0