ASP .Net - C# - Datagrid : selecting a row by clicking it (no button)
-
Hi Jeff, As you already know that the datagrid control is rendered to a table at the client side, so what you need to do is to create an event handler for the client side event
onlick
, in the handler you can easily determine the clicked row and post the page back to the server. At the server side, you can process the post back event to switch the datagrid to edit mode with the clicked row. You can take a look at some examples from here: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwebteam/html/webteam11062001.asp[^] [http://www.dotnetbips.com/ 5E3BBA5C-88FC-4053-8EC0-325C8C276F0E.aspx?articleid=205](http://www.dotnetbips.com/ 5E3BBA5C-88FC-4053-8EC0-325C8C276F0E.aspx?articleid=205)[[^](http://www.dotnetbips.com/ 5E3BBA5C-88FC-4053-8EC0-325C8C276F0E.aspx?articleid=205 "New Window")]Hi, Well I tried your solution and I think I badly explain what I really want to do. In fact I'd like when I click on a row to get the information from this particular row. The information could be on a array or whatever ... Is it possible ? Thx 4 your help. Jeff
-
Hi, Well I tried your solution and I think I badly explain what I really want to do. In fact I'd like when I click on a row to get the information from this particular row. The information could be on a array or whatever ... Is it possible ? Thx 4 your help. Jeff
Sorry I'm still unclear at this point. Am I correct in thinking that you have a datagrid displaying data, now instead of placing an Edit button(or link) in each row so that the user can click to select a particular row for editing, you might want the user to simply click on the row(or on any cells of the row) to select the row? When the user clicks on the row, the page should go back to the server and you want to get the information bound to the row. Or you want to get the information at the client side ? Can you be more specific about the context here? I'm sorry if I misunderstand your requirement.
-
Sorry I'm still unclear at this point. Am I correct in thinking that you have a datagrid displaying data, now instead of placing an Edit button(or link) in each row so that the user can click to select a particular row for editing, you might want the user to simply click on the row(or on any cells of the row) to select the row? When the user clicks on the row, the page should go back to the server and you want to get the information bound to the row. Or you want to get the information at the client side ? Can you be more specific about the context here? I'm sorry if I misunderstand your requirement.
minhpc_bk wrote: Am I correct in thinking that you have a datagrid displaying data, now instead of placing an Edit button(or link) in each row so that the user can click to select a particular row for editing, you might want the user to simply click on the row(or on any cells of the row) to select the row? When the user clicks on the row, the page should go back to the server and you want to get the information bound to the row. Yep you're right. It's what I'd like to do. Possible ? Thx.
-
minhpc_bk wrote: Am I correct in thinking that you have a datagrid displaying data, now instead of placing an Edit button(or link) in each row so that the user can click to select a particular row for editing, you might want the user to simply click on the row(or on any cells of the row) to select the row? When the user clicks on the row, the page should go back to the server and you want to get the information bound to the row. Yep you're right. It's what I'd like to do. Possible ? Thx.
There are a couple of options which you may consider: + Use a hidden edit column, then simply create event handlers for the onclick event for each item. In the event handler, we simulate the edit action like when the user clicks the Edit column. The sample code looks something like:
<%@ Page language="c#" %>
<%@ Import Namespace="System.Data"%>
<%@ Import Namespace="System.Data.SqlClient"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>WebForm</title>
<style>
.hiddenColumn{display:none}
</style>
<script runat="server" language="C#">
private void Page_Load(object sender, System.EventArgs e)
{
if(!IsPostBack)
{
BindGrid();
}
}private void BindGrid() { if(Session\["DataTable"\]==null) { string conString = "Initial Catalog=Northwind;Data Source=localhost; user=sa;password="; string cmdText = "select \* from Categories"; SqlDataAdapter adapter = new SqlDataAdapter(cmdText, conString); DataSet ds = new DataSet(); adapter.Fill(ds); Session\["DataTable"\] = ds.Tables\[0\]; } DataTable source = Session\["DataTable"\] as DataTable; DataGrid1.DataSource = source; DataGrid1.DataBind(); } protected void DataGrid\_EditCommand(Object sender, DataGridCommandEventArgs e) { DataGrid1.EditItemIndex = e.Item.ItemIndex; BindGrid(); } private void DataGrid1\_ItemCreated(object sender, System.Web.UI.WebControls.DataGridItemEventArgs e) { if(e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) { e.Item.Attributes.Add("onclick", "javascript:\_\_doPostBack('DataGrid1:\_ctl" + (e.Item.ItemIndex + 2) + ":\_ctl0','')"); } } </script> </HEAD> <body MS\_POSITIONING="GridLayout"> <form id="Form1" method="post" runat="server"> <asp:DataGrid id="DataGrid1" style="Z-INDEX: 101; LEFT: 68px; POSITION: absolute; TOP: 27px" runat="server" Height="231px" Width="375px" AutoGenerateColumns="False" OnItemCreated="DataGrid1\_ItemCreated" OnEditCommand="DataGrid\_EditCommand" > <Columns> <asp:BoundColumn DataField="CategoryID" HeaderText="CategoryID"></asp:BoundColumn> <asp:BoundColumn DataFi
-
There are a couple of options which you may consider: + Use a hidden edit column, then simply create event handlers for the onclick event for each item. In the event handler, we simulate the edit action like when the user clicks the Edit column. The sample code looks something like:
<%@ Page language="c#" %>
<%@ Import Namespace="System.Data"%>
<%@ Import Namespace="System.Data.SqlClient"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>WebForm</title>
<style>
.hiddenColumn{display:none}
</style>
<script runat="server" language="C#">
private void Page_Load(object sender, System.EventArgs e)
{
if(!IsPostBack)
{
BindGrid();
}
}private void BindGrid() { if(Session\["DataTable"\]==null) { string conString = "Initial Catalog=Northwind;Data Source=localhost; user=sa;password="; string cmdText = "select \* from Categories"; SqlDataAdapter adapter = new SqlDataAdapter(cmdText, conString); DataSet ds = new DataSet(); adapter.Fill(ds); Session\["DataTable"\] = ds.Tables\[0\]; } DataTable source = Session\["DataTable"\] as DataTable; DataGrid1.DataSource = source; DataGrid1.DataBind(); } protected void DataGrid\_EditCommand(Object sender, DataGridCommandEventArgs e) { DataGrid1.EditItemIndex = e.Item.ItemIndex; BindGrid(); } private void DataGrid1\_ItemCreated(object sender, System.Web.UI.WebControls.DataGridItemEventArgs e) { if(e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) { e.Item.Attributes.Add("onclick", "javascript:\_\_doPostBack('DataGrid1:\_ctl" + (e.Item.ItemIndex + 2) + ":\_ctl0','')"); } } </script> </HEAD> <body MS\_POSITIONING="GridLayout"> <form id="Form1" method="post" runat="server"> <asp:DataGrid id="DataGrid1" style="Z-INDEX: 101; LEFT: 68px; POSITION: absolute; TOP: 27px" runat="server" Height="231px" Width="375px" AutoGenerateColumns="False" OnItemCreated="DataGrid1\_ItemCreated" OnEditCommand="DataGrid\_EditCommand" > <Columns> <asp:BoundColumn DataField="CategoryID" HeaderText="CategoryID"></asp:BoundColumn> <asp:BoundColumn DataFi
Thx it works fine ! There was a little mistake here : e.Item.Attributes.Add("onclick", "javascript__doPostBack('DataGrid1:_ctl" + (e.Item.ItemIndex + 2) + ":_ctl0','" + e.Item.ItemIndex + "')"); And the right piece of code : e.Item.Attributes.Add("onclick", "javascript:__doPostBack('DataGrid1$_ctl" + (e.Item.ItemIndex + 2) + "$_ctl0','')"); Anyway thanx a lot for your help. See U. Jeff
-
Thx it works fine ! There was a little mistake here : e.Item.Attributes.Add("onclick", "javascript__doPostBack('DataGrid1:_ctl" + (e.Item.ItemIndex + 2) + ":_ctl0','" + e.Item.ItemIndex + "')"); And the right piece of code : e.Item.Attributes.Add("onclick", "javascript:__doPostBack('DataGrid1$_ctl" + (e.Item.ItemIndex + 2) + "$_ctl0','')"); Anyway thanx a lot for your help. See U. Jeff
Hi Jeff, Do you mean the delimiter
:
? In fact, that's not a mistake. When you view source of the page, and take a look at the function__doPostBack
you will see the code like this:theform.__EVENTTARGET.value = eventTarget.split("$").join(":");
The
split
method returns an array of sub strings seperated by the$
, and thejoin
method returns a string by concatenating all sub strings and seperating them by the:
So both theDataGrid1$_ctl8$_ctl0
andDataGrid1:_ctl8:_ctl0
return the same resultDataGrid1:_ctl8:_ctl0
when calling the above code. In addition, you can also make it better by create an event handler for theonmouseover
event, in the handler you can make the hand cursor appear when the user hovers on a row. -
There are a couple of options which you may consider: + Use a hidden edit column, then simply create event handlers for the onclick event for each item. In the event handler, we simulate the edit action like when the user clicks the Edit column. The sample code looks something like:
<%@ Page language="c#" %>
<%@ Import Namespace="System.Data"%>
<%@ Import Namespace="System.Data.SqlClient"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>WebForm</title>
<style>
.hiddenColumn{display:none}
</style>
<script runat="server" language="C#">
private void Page_Load(object sender, System.EventArgs e)
{
if(!IsPostBack)
{
BindGrid();
}
}private void BindGrid() { if(Session\["DataTable"\]==null) { string conString = "Initial Catalog=Northwind;Data Source=localhost; user=sa;password="; string cmdText = "select \* from Categories"; SqlDataAdapter adapter = new SqlDataAdapter(cmdText, conString); DataSet ds = new DataSet(); adapter.Fill(ds); Session\["DataTable"\] = ds.Tables\[0\]; } DataTable source = Session\["DataTable"\] as DataTable; DataGrid1.DataSource = source; DataGrid1.DataBind(); } protected void DataGrid\_EditCommand(Object sender, DataGridCommandEventArgs e) { DataGrid1.EditItemIndex = e.Item.ItemIndex; BindGrid(); } private void DataGrid1\_ItemCreated(object sender, System.Web.UI.WebControls.DataGridItemEventArgs e) { if(e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) { e.Item.Attributes.Add("onclick", "javascript:\_\_doPostBack('DataGrid1:\_ctl" + (e.Item.ItemIndex + 2) + ":\_ctl0','')"); } } </script> </HEAD> <body MS\_POSITIONING="GridLayout"> <form id="Form1" method="post" runat="server"> <asp:DataGrid id="DataGrid1" style="Z-INDEX: 101; LEFT: 68px; POSITION: absolute; TOP: 27px" runat="server" Height="231px" Width="375px" AutoGenerateColumns="False" OnItemCreated="DataGrid1\_ItemCreated" OnEditCommand="DataGrid\_EditCommand" > <Columns> <asp:BoundColumn DataField="CategoryID" HeaderText="CategoryID"></asp:BoundColumn> <asp:BoundColumn DataFi
Could you shed some light on the __doPostBack paramter "DataGrid1$_ctl2$_ctl0" DataGrid1 (the control) _ctl2 (? the row of the table) Why do you take the index and + 2 _ctl0 (? got me) Thank you
-
Could you shed some light on the __doPostBack paramter "DataGrid1$_ctl2$_ctl0" DataGrid1 (the control) _ctl2 (? the row of the table) Why do you take the index and + 2 _ctl0 (? got me) Thank you
Hi there, This is a naming convention in the datagrid control. Because the datagrid control(also DataList, Repeater ...) is a naming container (implements the
INamingContainer
interface), so it makes sure that theid
values of its child controls are unique on a web page. Now we go back to your question. Dominic Farr wrote: _ctl2 (? the row of the table) Why do you take the index and + 2 The format of it is_ctl<row_number>,
and therow_number
is a 1-based value, not zero-based, so it should start with 1, then 2, 3 and so on ....And as you may already know that the datagrid control is rendered to a table at the client side, and the row 1 is the header of the table, the data rows start from the row 2. Meanwhile, theDataGrid.Items
property contains a collection of the DataGridItem objects, and each object DataGridItem represents a data row in the table. The index of the DataGridItem is a zero-based value, and you need to remember that this collection does not contain the header of the table. So therow_number
of the data rows (not header) should be calculated as(Item.ItemIndex + 2)
. Dominic Farr wrote: _ctl0 (? got me)_ctl<control_index>
As I said earlier, the DataGrid needs to ensure that all of its child controls are uniquely identifiable on the web page. So if there is any child control in the row that has no id value specified, the grid will automatically add the unique id for the control, and thecontrol_index
should start from 0. In the sample code provided in my post, there are 3 columns in the grid, and the two first columns are the boundcolumn which render as text. But the last column contains a linkbutton in there, so the naming container automatically adds the id _ctl0 for each linkbutton. Assume that, you now might want to place a template column as below before the edit column:<asp:TemplateColumn HeaderText="Header">
<ItemTemplate>
<asp:HyperLink Runat="server" NavigateUrl="...">Text</asp:HyperLink>
</ItemTemplate>
</asp:TemplateColumn>
<asp:EditCommandColumn ButtonType="LinkButton" UpdateText="Update" HeaderText="Command" CancelText="Cancel"
EditText="Edit"></asp:EditCommandColumn>Because the hyperlink control in the template column does not specify the id, so the grid will automatically add the
_ctl0
fo -
There are a couple of options which you may consider: + Use a hidden edit column, then simply create event handlers for the onclick event for each item. In the event handler, we simulate the edit action like when the user clicks the Edit column. The sample code looks something like:
<%@ Page language="c#" %>
<%@ Import Namespace="System.Data"%>
<%@ Import Namespace="System.Data.SqlClient"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>WebForm</title>
<style>
.hiddenColumn{display:none}
</style>
<script runat="server" language="C#">
private void Page_Load(object sender, System.EventArgs e)
{
if(!IsPostBack)
{
BindGrid();
}
}private void BindGrid() { if(Session\["DataTable"\]==null) { string conString = "Initial Catalog=Northwind;Data Source=localhost; user=sa;password="; string cmdText = "select \* from Categories"; SqlDataAdapter adapter = new SqlDataAdapter(cmdText, conString); DataSet ds = new DataSet(); adapter.Fill(ds); Session\["DataTable"\] = ds.Tables\[0\]; } DataTable source = Session\["DataTable"\] as DataTable; DataGrid1.DataSource = source; DataGrid1.DataBind(); } protected void DataGrid\_EditCommand(Object sender, DataGridCommandEventArgs e) { DataGrid1.EditItemIndex = e.Item.ItemIndex; BindGrid(); } private void DataGrid1\_ItemCreated(object sender, System.Web.UI.WebControls.DataGridItemEventArgs e) { if(e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) { e.Item.Attributes.Add("onclick", "javascript:\_\_doPostBack('DataGrid1:\_ctl" + (e.Item.ItemIndex + 2) + ":\_ctl0','')"); } } </script> </HEAD> <body MS\_POSITIONING="GridLayout"> <form id="Form1" method="post" runat="server"> <asp:DataGrid id="DataGrid1" style="Z-INDEX: 101; LEFT: 68px; POSITION: absolute; TOP: 27px" runat="server" Height="231px" Width="375px" AutoGenerateColumns="False" OnItemCreated="DataGrid1\_ItemCreated" OnEditCommand="DataGrid\_EditCommand" > <Columns> <asp:BoundColumn DataField="CategoryID" HeaderText="CategoryID"></asp:BoundColumn> <asp:BoundColumn DataFi
-
Hi there, This is a naming convention in the datagrid control. Because the datagrid control(also DataList, Repeater ...) is a naming container (implements the
INamingContainer
interface), so it makes sure that theid
values of its child controls are unique on a web page. Now we go back to your question. Dominic Farr wrote: _ctl2 (? the row of the table) Why do you take the index and + 2 The format of it is_ctl<row_number>,
and therow_number
is a 1-based value, not zero-based, so it should start with 1, then 2, 3 and so on ....And as you may already know that the datagrid control is rendered to a table at the client side, and the row 1 is the header of the table, the data rows start from the row 2. Meanwhile, theDataGrid.Items
property contains a collection of the DataGridItem objects, and each object DataGridItem represents a data row in the table. The index of the DataGridItem is a zero-based value, and you need to remember that this collection does not contain the header of the table. So therow_number
of the data rows (not header) should be calculated as(Item.ItemIndex + 2)
. Dominic Farr wrote: _ctl0 (? got me)_ctl<control_index>
As I said earlier, the DataGrid needs to ensure that all of its child controls are uniquely identifiable on the web page. So if there is any child control in the row that has no id value specified, the grid will automatically add the unique id for the control, and thecontrol_index
should start from 0. In the sample code provided in my post, there are 3 columns in the grid, and the two first columns are the boundcolumn which render as text. But the last column contains a linkbutton in there, so the naming container automatically adds the id _ctl0 for each linkbutton. Assume that, you now might want to place a template column as below before the edit column:<asp:TemplateColumn HeaderText="Header">
<ItemTemplate>
<asp:HyperLink Runat="server" NavigateUrl="...">Text</asp:HyperLink>
</ItemTemplate>
</asp:TemplateColumn>
<asp:EditCommandColumn ButtonType="LinkButton" UpdateText="Update" HeaderText="Command" CancelText="Cancel"
EditText="Edit"></asp:EditCommandColumn>Because the hyperlink control in the template column does not specify the id, so the grid will automatically add the
_ctl0
foExcellent. Thanks