GeekZilla
Select a row in an asp:GridView without using a Select Command
ASP.Net's GridViews can be quite useful, but beware of binding them to huge datasets as this has an overhead on the ViewState.
Often you'll want to display a number of columns on each line and row space becomes an issue. What's worse is you then have to create a SELECT command button to be able to access that line's data.
<asp:CommandField ShowInsertButton="true" />
Use the following code on the event OnRowDataBound to eliminate the need for the SELECT command field and save yourself some valuable space.
Here is the HTML to create a GridView, I'm displaying a list of people, and the key for each record is the PERSON_ID.
<asp:GridView ID="PeopleGridView" runat="server" AutoGenerateColumns="False" DataKeyNames="PERSON_ID" DataSourceID="PeopleDataObject" Width="200px" OnRowDataBound="PeopleGridView_RowDataBound" AllowPaging="True"> <Columns> <asp:BoundField DataField="USER_NAME" HeaderText="Name" SortExpression="USER_NAME" > </asp:BoundField> </Columns> </asp:GridView>
The key event to note is the OnRowDataBound, use the following code to create SELECT functionality on the row.
protected void PeopleGridView_RowDataBound(object sender, GridViewRowEventArgs e) { if (e.Row.RowType == DataControlRowType.DataRow) { e.Row.Attributes["onmouseover"] = "this.style.cursor='hand';this.style.textDecoration='underline';"; e.Row.Attributes["onmouseout"] = "this.style.textDecoration='none';"; e.Row.Attributes["onclick"] = ClientScript.GetPostBackClientHyperlink(this.PeopleGridView, "Select$" + e.Row.RowIndex); } }
Each row will then behave like a link, and when you select one it can drive the behavior of another control(s) on your page, possibly a DetailsView allowing you to INSERT a complete record to the database.
A self confessed Microsoft bigot, Paul loves all Microsoft products with a particular fondness for SQL Server. Paul is currently focusing on Web 2.0 patterns and practices and is always looking for better ways of doing things.
I love the .net platform, and I find it to be the most productive toolset I have used to date.
Comments
Anonymous
said:
This only seems to work in framework 2.0 if you add enableEventValidation="false" to the page directive in web.config, which is not recommended
Paul Marshall
said:
In response to the comment regarding enableEventValidation being set to false. You don't need to do that, I've gone back to my implemention of this and its set to true in both the page and the web.config
I have never used this in previous versions of the framework and this example was lifted from a .net 2.0 project.
Happy coding.....
Edgar
said:
Sadly I found the enableEventValidation issue too.
Any suggestions?. Thx
Paul Marshall
said:
I'd suggest that you look that the data in your GridView, and the other controls on your page.
You will probably have data that is upsetting your viewstate. e.g. HTML code in a text box.
What is the error message you're getting?
said:
I have the same problem when I click on the row on the gridview I get the enablepagevalidation = true error. If I have a select field visable on the gridview then it works ok when clicked. If I remove this it does not and it willnot fire the SelectedIndexChanged event on the gridview Please can you help
Khalegh Ahmadi, Khalegh@GMail.com
said:
You can solve the invalidation problem very easy :
Use the select CommandField and set it's visible property to true. Then set the Display Style of Both the Item Style and Header Style to none.
Set the ItemStyle-CssClass and HeaderStyle-CssClass properties to a class created in a StyleSheet File which contains the Dispaly Style.
For Example :
.HideButton {Display : none}
and in Gridview add the Select CommandField :
<asp:CommandField SelectText ="Select" ShowSelectButton="true"
ItemStyle-CssClass = "HideButton" HeaderStyle-CssClass ="HideButton" />
Khalegh
said:
You can solve the event invalidation problem very easy :
Create a StyleSheet File and write the following class in it :
.HideButton { Display : none}
Then
Use the Select CommandField and set it's Visible property to true and set both the ItemStyle-CssClass and HeaderStyle-CssClass to HideButton :
<asp:CommandField SelectText ="Select" ShowSelectButton="true"
ItemStyle-CssClass = "HideButton" HeaderStyle-CssClass ="HideButton" />
Anup Garg
said:
It really worked for me after making changes in config. Thanx.
Levi
said:
I want to select row in the gridview only when the GridView.Enabled is true.
Is there any solution?
Levi
said:
Thank You, I found the solution.
"if (GridView1.Enabled) Select$" + e.Row.RowIndex);
Anonymous
said:
I love the solution, thanks. One issue with it though. Currently if I select one, on a Paged Gridview (allow paging), if I switch pages, the selection is moved to the current page at the same index in the page. How can this be changed to clear the selection when I switch pages?
Manuj
said:
Thanks It works Good with GridView in framework2.0
Gagan
said:
Thanks Paul. It is exact what i was looking for.
YK
said:
GridView settings:
EnabledViewState = false
LinkButton set as CommandName=Select
SelectedIndexChanged event is not fired which take me to other page.
When I set EnableViewState = true, it works fine.
Any suggestions
mary
said:
hi tried this example but i am getting the follwing error just tell me how to clear it
Invalid postback or callback argument. Event validation is enabled using <pages enableEventValidation="true"/> in configuration or <%@ Page EnableEventValidation="true" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation.
yrksundeep
said:
can some one help me how to bind the details view by selecting a row using rowdatabound event in a grid view. i need the contiuation for this code.
darshan
said:
i tried but i m getting the following erro so plz give me solution
and how to post back to new page record as per that record selection
Invalid postback or callback argument. Event validation is enabled using <pages enableEventValidation="true"/> in configuration or <%@ Page EnableEventValidation="true" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation.
said:
For those that are getting the validation issue, I have solved it in my project by adding the following (be sure to replace the "GridViewControlName" with your own:
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
'The following line of code is required when doing a manual postback from client script. Page.ClientScript.RegisterForEventValidation(GridViewControlName.UniqueID) MyBase.Render(writer) End Sub
DR
said:
The mouseover doesn't work in FF. I can get the same effect with styles.
kenyu
said:
thanks Paul,it does work for me.
owen
said:
very usefull. thanks
michel
said:
Any1 any idea how to set the row background to another color onmouseover? Just adding this.style.background-color:gray; doesn't work
Joey J. Barrett
said:
Perfect solution thank you.
What I did:
The GridView is in a UpdatePanel and each selection is stored in a session allowing the user to make multiple selections then act on them.
lis716
said:
i'm using visual basic and the codes seems not to work at all. do i have to declare it ? like for example this code e.Row.Attributes["onmouseover"] = "this.style.cursor='hand';this.style.textDecoration='underline';";
the "e" needs a declaration.
and the format of the code like the parethesis forst before the if does not work too...
pls help!
Aladdin
said:
Thanks Paul and Khalegh - it works perfectly well using both your codes.
vishal
said:
thanks for the solution, but i am getting a wierd behaviour , for paging enabled in the grid, after i go to next page, i get the same data on the previous ( first ) page ( from dataset ) on clicking on a row on second/next page..
yamini
said:
it is nice
KathyPDX
said:
That is so cool! Works great, thanks.
ousama
said:
hello paul,
i just one question and i hope you could help me because i have been surfing the net for a week and i could not find the answer. when my application goes from one page to another based on a selected row in my grid i want ,when i click on the back button, to see the selected already kept selected in the privouse table. i hope it is clear for you thanks in advanced
Ryan
said:
The VB version of this code:
Protected Sub YourGridName_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs)
If (e.Row.RowType = DataControlRowType.DataRow) Then e.Row.Attributes.Add("onmouseover", "this.style.cursor='hand';this.style.textDecoration='underline';") e.Row.Attributes.Add("onmouseout", "this.style.textDecoration='none';") e.Row.Attributes.Add("onclick", ClientScript.GetPostBackClientHyperlink(Me.YourGridName, "Select$" + e.Row.RowIndex.ToString())) End If
End Sub
Note here that I'm not using a handler for this function. If you do this funciton gets called twice every time you click a row - once from the OnRowDataBound property in the gridview, and the other from the handler.
To get this to work if you are getting the " Event validation is enabled using..... " error, I reccommend using Khalegh Ahmadi's hack. I have tried it and it works beautifully. The way I understand it is he tricks server into thinking that postback came from the server control.
A few things to note with his hack is that if you haven't already, you need to add a link to the stylesheet you are going to use up the top of your aspx page between the <head> </head> tags, something like:
<link rel="Stylesheet" href="stylesheet.css" type="text/css" />
trycatchscenario
said:
Ok I found a easier solution for those who just want to disable it for the page rather the the config file for the whole project. On the top of the .aspx page add this line
<%@ Page EnableEventValidation="false" %>
said:
What if the gridview have a deletebutton column which does not want to bahave like a link ?
marshp3
said:
You could set the button to not "bubble" the event to the row.
Skype me or Google to find out how to do it
Ranch
said:
Thanks Paul! Very nice Code!
cxspan
said:
The guy who posted (and didn't leave a name) on April 26, 2007 - 9:24 PM was on the right track. You need to override the Render function and add the onclick/styling code here. Remove this code from the RowDataBound function and DO NOT DISABLE EVENT VALIDATION!
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
AddRowSelectToGridView(GridView1); AddRowSelectToGridView(GridView2); AddRowSelectToGridView(GridView3); base.Render(writer);
}
private void AddRowSelectToGridView(GridView gv)
{
foreach (GridViewRow row in gv.Rows) { row.Attributes["onmouseover"] = "this.style.cursor='hand';this.style.textDecoration='underline';"; row.Attributes["onmouseout"] = "this.style.textDecoration='none';"; row.Attributes.Add("onclick", Page.ClientScript.GetPostBackEventReference(gv, "Select$" + row.RowIndex.ToString(), true)); }
}
Nev
said:
Thanks Paul,,really work wonders. did'nt know of this feature in the fridview..Excellent!!
Nev
said:
Excellent work Paul!!
ahm
said:
i need to display in textboxes when i click a particular row in gridview by using asp.net using vb.net
Tarun
said:
All soutions works fine so long as you dont have any other command like delete, edit in the gridview.
if you have it, then if you click delete, first select and then delete command will be fired, resulting two postbacks.
i am curious if someone posts a solution for this
dipak sanki
said:
when i click a particular row in gridview,i need to display another gridview by using asp.net using C#
amanda
said:
hi. the code work great, thanks!! i was also wondering what extra steps/codes necessay it make the clicked item redirect to another page and at the same time extracting its value. any tips would help thanks again.
sushanth
said:
hey...it works great, only put.. the EnableEventvalidation="false" in the .aspx page.. it works fine.
this is my entire .cs code file :
public partial class Default3 : System.Web.UI.Page
{
static string connection = System.Configuration.ConfigurationManager.ConnectionStrings["EhrmConnectionString"].ToString(); SqlConnection con = new SqlConnection(connection); protected void Page_Load(object sender, EventArgs e) { con.Open(); try { SqlCommand cmd1 = new SqlCommand("select * from Admin_HRMS_Grade", con); SqlDataAdapter adp = new SqlDataAdapter(cmd1); DataSet ds = new DataSet(); adp.Fill(ds, "Admin_HRMS_Grade"); GridView1.DataSource = ds; GridView1.DataBind(); } catch (Exception ce) { Response.Write(ce.Message + ce.StackTrace); } finally { con.Close(); } } protected void Gridview1_page(object sender, System .Web .UI .WebControls .GridViewPageEventArgs e) { GridView1.PageIndex = e.NewPageIndex; GridView1.DataBind(); }
protected void Submit1_ServerClick(object sender, EventArgs e) { try { con.Open(); SqlCommand cmd = new SqlCommand("Admin_HRMS_Grade_Insert", con); cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("@Grade_name", Text2.Value); cmd.Parameters.AddWithValue("@Grade_desc", TEXTAREA1.Value); cmd.Parameters.AddWithValue("@Grade_band", Text3.Value); if (Radio1.Checked == true) { cmd.Parameters.AddWithValue("@Status",1); } else if (Radio2.Checked == true) { cmd.Parameters.AddWithValue("@Status",0); } cmd.ExecuteNonQuery(); } catch (Exception ce) { Response.Write(ce.Message + ce.StackTrace); } finally { con.Close(); } }
protected void Button1_Click(object sender, EventArgs e) { try { con.Open(); SqlCommand cmd2= new SqlCommand("select * from Admin_HRMS_Grade where Grade_Name='"+Text1.Value+"'", con); SqlDataAdapter adp2 = new SqlDataAdapter(cmd2); DataSet ds2 = new DataSet(); adp2.Fill(ds2, "Admin_HRMS_Grade"); GridView1.DataSource = ds2; GridView1.DataBind(); } catch { } finally { con.Close(); } } protected void GridView1_SelectedIndexChanged(object sender, EventArgs e) { try {
string a; con.Open(); GridViewRow row = GridView1.SelectedRow; //Text1.Value = row.Cells[1].Text;
Text1.Value = GridView1.SelectedRow.Cells[1].Text; a = Text1.Value; } catch { } finally { } } protected void GridView1_SelectedIndexChanging(object sender, GridViewSelectEventArgs e) { try { GridViewRow row = GridView1.Rows[e.NewSelectedIndex]; } catch { } finally { }
} protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e) { if (e.Row.RowType == DataControlRowType.DataRow) { e.Row.Attributes["onmouseover"] = "this.style.cursor='hand';this.style.textDecoration='underline';this.style.backColor='Red'"; e.Row.Attributes["onmouseout"] = "this.style.textDecoration='none';"; e.Row.Attributes["onclick"] = ClientScript.GetPostBackClientHyperlink(this.GridView1, "Select$" + e.Row.RowIndex); } }
}
deive
said:
Thanks cxspan - that was exactlly what was needed
Lawrence
said:
Hi,
How about this?
protected void gridview1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "MySelect") { GridViewRow mySelectedRow = ((GridViewRow)(((DataControlFieldCell)(((WebControl)(e.CommandSource)).Parent)).Parent)); int mySelectedRowIndex = mySelectedRow.RowIndex; }
}
In your source code: ASPX:
........
<asp:TemplateField ShowHeader="False">
<ItemTemplate>
<asp:LinkButton ID="lnkMySelect" runat="server" Text="MySelect"
CausesValidation="False" CommandName="MySelect" /> </ItemTemplate> </asp:TemplateField>
..........
This would allow you to have access to the GridViewRow of the clicked link.
Hope this helps!
Alex
said:
Hi there.
I get an error saying:
The name 'ClientScript' does not exist in the current context
any help would be greatly appreciated
WildCow
said:
For Alex:
Page.ClientScript (I had to search for that one too...).
For me:
I can't get the mouse icon to change in FireFox, only in IE. Anyone succeeded?
Pheno
said:
@WildCow
You have to use this.style.cursor='pointer';
JohnJacob
said:
@Alex:
Try using this.style.cursor='pointer' instead of this.style.cursor='hand'
ST
said:
Thanks paul your information on the on click it helped me. Now I have another question I am trying to add a line to an existing gridview I click on a line and would like to add a line under the line I clicked on.
Thanks
Harrison
said:
Thank you so much guys for all your contribution. I have gotten the completed the skeletal work. but this is work I'm having problems
How can you access to the index of the Row that's been selected?
I only allowing it to select one item at a time.
Thank you so much guys!
David
said:
I ran across this and some other posts that proposed the same basic approach, however I ended up getting an error message related to Validation being set to true. (I don't recall the exact wording of it.)
As an alternative, I adapted the solution slightly to to hard code the 'javascript:_doPostBack()' into a string using the same variables to create the proper references. The result is that the onClick is generated with the Page.ClientScript.GetPostBackEventReference().
Sub gridView_ShowList_RowCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs)
Dim functionName As String
'Note that the gridview name is hard coded, the original code uses the sender object, but I couldn't get it to work
'in concatenating the string
functionName = "javascript:_doPostBack('gridViewShowList'" "," "'" "Select$" & e.Row.RowIndex.ToString "')"
If e.Row.RowType = DataControlRowType.DataRow Then
e.Row.Attributes.Add("onclick", functionName)
End If
End Sub
nikki
said:
Thanks. It helped me alot.
mmogan
said:
Hi Paul,
thanks for the solution, but i am getting a problem, for paging enabled in the grid, after i go to next page, i get the same data on the previous ( first ) page ( from dataset ) on clicking on a row on second/next page...Please help me with a solution
mmogan
said:
Hi folks,
I got a solution for paging issue. ie binding of the data has to be done with the gridview. in the page index changing method.
Protected Sub gvEmp_PageIndexChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewPageEventArgs) Handles gvEmp.PageIndexChanging gvEmp.PageIndex = e.NewPageIndex gvEmp.DataBind() End Sub
Hope this helps most of us.
SuikerSays:
said:
Hey smart thinking!
I also liked cxspan's approach!
Way to go! guys!
Cenk Taylan Düz
said:
protected override void Render(System.Web.UI.HtmlTextWriter writer) { AddRowSelectToGridView(GridView1); base.Render(writer);
} private void AddRowSelectToGridView(GridView gv) { if (gv.EditIndex == -1) { foreach (GridViewRow row in gv.Rows) { row.Attributes["onmouseover"] = "this.style.cursor='hand';this.style.textDecoration='underline';"; row.Attributes["onmouseout"] = "this.style.textDecoration='none';"; row.Attributes.Add("onclick", Page.ClientScript.GetPostBackEventReference(gv, "Select$" + row.RowIndex.ToString(), true)); } } }
A Little Change In Code
if you add "(gv.EditIndex == -1)"
You can Edit on gridview
Rupesh Bari
said:
Thank you so much frnd...You solve my this critical problem if any one want to hide allowSelectButton then write simply in <Columns>.
<asp:CommandField SelectText=" " ShowSelectButton="True" />
do not add AutoGenerateSelectButton="true" in <asp:Gridview> Section...
Lawty
said:
Having searching for ages, reading countless blogs why the SelectedIndexChanged event was refusing to trigger on my GridView - trying several suggestions and failing - finally I found the comment left by cxspan - and it works. You are a genius!!!
ASMGX
said:
Thanks cxspan
your code works
srishti
said:
On Clicking hyperlink in gridview and i want to pass some value to the next page how to pass the selected row cell value to next page...
Hrushikesh/ India
said:
This is great. Thanks a lot.
vegeta
said:
hi paul
im using a master page which includes a search panel.when i search an employee i used to show all the employees in gridview and i can select the employee by clikin on gridview row.when i clik on gridview row im creating a session variable of that employee's ID.
but im not gettin that session var in content page bcuz content page loads first.im gettin that session var on second page-load. how to resolv this issue.
i tried to access session var by including that search functionality into webform but still im getting the same scene(i.e im gettin the session var at second postback) Please help.......
said:
please if u can mail me at this id aloklingayat@gmail.com ill be very thankfull...
wizzle
said:
im using this code and it works fine when the panel the gridview is contained in is set to enabled. but when the panel is disabled i get the validation error. how can i set this so you can only select when the panel is enabled without disabled the validation?
Enrique
said:
Gracias por la enorme ayuda!!!
thanks a lot!.
bhasker
said:
pl resolve my problem. i am getting following error while using your above code...
Invalid postback or callback argument. Event validation is enabled using <pages enableEventValidation="true"/> in configuration or <%@ Page EnableEventValidation="true" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation.
animalistix
said:
this is really cool helped me alot. thanks
MCinDaBurgh
said:
Thanks for the post.
I am doing something similar in vb.net and I have the row click functionality working but realize now instead I need to only do this for an imageButton (expand/collapse). do you know how to do this?
Specifically I need to know about the clientID syntax.Ex, i am trying to do something like this:
Dim MyImgButton As ImageButton
MyImgButton=CType(MyGridView.SelectedRow.FindControl("imgButton"), ImageButton)
MyImgButton.Attributes.Add("onclick", Page.ClientScript.GetPostBackEventReference(MyGridView, "Select$" + MyImgButton.ClientID, True))
so I am looking for this part: "Select$" + MyImgButton.ClientID
not sure what to put there, if anyone has an idea about this please let me know.
thx
MC
said:
I have the problem when I click on the row on the gridview I get the enablepagevalidation = true error. If I have a select field visable on the gridview then it works ok when clicked. If I remove this it does not and it willnot fire the SelectedIndexChanged event on the gridview Please can you help
Matt
said:
Cheers cxspan, moving this code into the render event (where it can be registered for event validation) solved all my problems - kudos!
MarKus
said:
it worked fine, Thx
Edgardo
said:
Even 4 years after being published this is still veryn helpful, save me a lot of time for a project I am working in..... Thanks Paul.
rgtidwell
said:
Thanks! Works GREAT!!
varsha
said:
I use in my application but it not works in mozila but the hand cursor is not display.
Name
said:
Tks cxspan
jboeke
said:
Upvote to cxspan! Yours really is the most elegant solution and also avoid disabling EventValidation. Cheers!
Reza
said:
Hello Michel,
use
this.style.backgroundColor='Gray' instade of this.style.background-color:gray
Merrill Reddy
said:
Page works fine after adding this parts
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
AddRowSelectToGridView(GridView1); AddRowSelectToGridView(GridView2); AddRowSelectToGridView(GridView3); base.Render(writer);
}
private void AddRowSelectToGridView(GridView gv)
{
foreach (GridViewRow row in gv.Rows) { row.Attributes["onmouseover"] = "this.style.cursor='hand';this.style.textDecoration='underline';"; row.Attributes["onmouseout"] = "this.style.textDecoration='none';"; row.Attributes.Add("onclick", Page.ClientScript.GetPostBackEventReference(gv, "Select$" + row.RowIndex.ToString(), true)); }
}
Micheal
said:
Awsome