ASP.NET GridView within Scrollable Div: Scroll to SelectedIndex

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP



ASP.NET GridView within Scrollable Div: Scroll to SelectedIndex



I have a GridView contained within a scrollable div. I also have a Button that selects a row in this GirdView based upon the text of a TextBox on the page. The row is selected just fine, but I cannot get the div to scroll to the selected row programmatically. I have attempted multiple methods involving JavaScript's "scrollTop" method, but for some reason I cannot get them to work correctly. Here is my code so far (some of the code for the "btnGo_OnClick" method is taken from an answer to a similar question on the asp.net forums, but it does not appear to be working for me):



The .aspx file:


<%@ Page Title="" Language="C#" MasterPageFile="~/Site1.Master" AutoEventWireup="true"
CodeBehind="StudentList.aspx.cs" Inherits="WebApplication1.WebForm1" %>

<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<br />
<div style="overflow: scroll; height: 400px;">
<asp:GridView ID="StudentList" runat="server" AutoGenerateColumns="False" DataSourceID="DataSource1"
AllowSorting="true" CellPadding="4" DataKeyNames="Email">
<Columns>
<asp:BoundField DataField="LastName" HeaderText="Last" ReadOnly="True" SortExpression="LastName" />
<asp:BoundField DataField="FirstName" HeaderText="First" ReadOnly="True" SortExpression="FirstName" />
<asp:BoundField DataField="MiddleInitial" HeaderText="Middle" ReadOnly="True" SortExpression="MiddleInitial" />
<asp:BoundField DataField="Phone" HeaderText="Phone" ReadOnly="True" SortExpression="Phone" />
<asp:BoundField DataField="Email" HeaderText="Email" ReadOnly="True" SortExpression="Email" />
<asp:BoundField DataField="GPA" HeaderText="GPA" ReadOnly="True" SortExpression="GPA" />
<asp:TemplateField HeaderText="">
<ItemTemplate>
<asp:Button ID="btnEdit1" Text="Edit" AutoPostBack="True" runat="server" OnClick="btnEdit1_OnClick" />
&nbsp
<asp:Button ID="btnDelete" Text="Delete" AutoPostBack="True" runat="server" OnClick="btnDelete_OnClick" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
<SelectedRowStyle BackColor="Black" ForeColor="White" />
</asp:GridView>
</div>
<br />
<br />
Search by Last Name:
<asp:TextBox ID="txtSearch" runat="server"></asp:TextBox>
&nbsp
<asp:Button ID="btnGo" Text="Go" AutoPostBack="True" runat="server" OnClick="btnGo_OnClick" />
<br />
<br />
<asp:Label ID="lbl1" runat="server" Text=""></asp:Label>
<asp:AccessDataSource ID="DataSource1" runat="server" DataFile="~/App_Data/University(2).accdb"
SelectCommand="SELECT [LastName], [FirstName], [MiddleInitial], [Phone], [Email], [GPA]
FROM [Students] ORDER BY [LastName]" DeleteCommand=""></asp:AccessDataSource>
</asp:Content>



And the .aspx.cs file:


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

namespace WebApplication1

public partial class WebForm1 : System.Web.UI.Page


protected void Page_Load(object sender, EventArgs e)



protected void btnDelete_OnClick(object sender, EventArgs e)

Button b = (Button)sender;
GridViewRow containingRow = (GridViewRow)b.NamingContainer;
String strEmail = containingRow.Cells[4].Text;
DataSource1.DeleteCommand = "DELETE FROM [CoursesTaken] WHERE [StudentID] = '" + strEmail + "'";
DataSource1.Delete();
DataSource1.DeleteCommand = "DELETE FROM [Students] WHERE [Email] = '" + strEmail + "'";
DataSource1.Delete();
StudentList.DataBind();


protected void btnEdit1_OnClick(object sender, EventArgs e)

Button b = (Button)sender;
GridViewRow containingRow = (GridViewRow)b.NamingContainer;
Session["Email"] = containingRow.Cells[4].Text;
Response.Redirect("~/StudentEdit.aspx");


protected void btnGo_OnClick(object sender, EventArgs e)

int i = 0;
foreach (GridViewRow rowItem in StudentList.Rows)

if (rowItem.Cells[0].Text.StartsWith(txtSearch.Text))

StudentList.SelectedIndex = i;
int intScrollTo = this.StudentList.SelectedIndex * (int)this.StudentList.RowStyle.Height.Value;
string strScript = "";
strScript += "var gridView = document.getElementById('" + this.StudentList.ClientID + "');n";
strScript += "if (gridView != null && gridView.parentElement != null && gridView.parentElement.parentElement != null)n";
strScript += " gridView.parentElement.parentElement.scrollTop = " + intScrollTo + ";n";
ScriptManager.RegisterClientScriptBlock(this.Page, this.GetType(), "btnGo_OnClick", strScript, true);
break;

i++;







Can someone explain why it's not working as expected?




3 Answers
3



Some bit of javascript can help. Have a look at the following post: https://stackoverflow.com/a/4558637/145682



Here is a POC:



Markup:


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

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<style type="text/css">
#form1

height: 225px;

</style>
<script>
function focusRow(id, rowIndex)
var tbl = document.getElementById(id);
var rows = tbl.childNodes[0].childNodes;
rows[rowIndex].childNodes[0].focus();
document.getElementById('console').innerText = rows[rowIndex].childNodes[0].innerHTML;

</script>
</head>
<body>
<form id="form1" runat="server">
<div style="padding:10px; background-color:lightblue; height:105px; overflow:scroll;">
<asp:GridView ID="GridView1" runat="server">
<SelectedRowStyle BackColor="Yellow" />
</asp:GridView>
</div>
<div>
<asp:DropDownList ID="ddlSelectIndexes" runat="server"></asp:DropDownList>
<asp:Button ID="btnSelect" runat="server" Text="Select" OnClick="btnSelect_Click" />
<div id="console"></div>
</div>
</form>
</body>
</html>



Code Behind:


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

namespace GridViewScrollIndex

public partial class Default : System.Web.UI.Page

protected void Page_Load(object sender, EventArgs e)

if (!IsPostBack)

var arr = Enumerable.Range(1, 100);
GridView1.DataSource = arr;
GridView1.DataBind();
ddlSelectIndexes.DataSource = arr.Select(x=> new f1=x, f2=x);
ddlSelectIndexes.DataValueField = "f1";
ddlSelectIndexes.DataTextField = "f2";
ddlSelectIndexes.DataBind();



protected void btnSelect_Click(object sender, EventArgs e)

string selVal = ddlSelectIndexes.SelectedValue;
int i=0;
foreach (GridViewRow row in GridView1.Rows)

if (row.RowType == DataControlRowType.DataRow)

if (row.Cells[0].Text == selVal)

GridView1.SelectedIndex = i;
ScriptManager.RegisterStartupScript(GridView1, this.GetType(), "highlight",
string.Format("window.onload = function() 2 focusRow('0', 1); 3;", GridView1.ClientID, i+1, "", ""), true);
break;


i++;






Hope this helps.





I will adapt your idea for my code and report whether or not it is successful.
– ScottRobertLane
Jul 10 '13 at 17:35





Debugging this example gives the following error: "Microsoft JScript runtime error: Unable to get value of the property 'childNodes': object is null or undefined" for the following line in the script in the Markup page: "rows[rowIndex].childNodes[0].focus();". Why is this?
– ScottRobertLane
Jul 10 '13 at 18:02






Its possible you are getting the wrong reference. However I'd have to see your adapted code to be sure. Put in some site like pastebin. What browser are you using? In your debugger try letting me know what the following outputs: rows[rowIndex].tagName
– deostroll
Jul 11 '13 at 4:32


rows[rowIndex].tagName





My modified code has been uploaded as an answer to this question, along with details about my browser and the value you asked about.
– ScottRobertLane
Jul 11 '13 at 21:03





@ScottRobertLane What version of IE are you using? Inside the js function your goal should be to seek the tr and its nested td element corresponding to the rowIndex value passed as argument to the function. So perhaps the subscript you are assigning to the childNodes property will vary...you have to debug and find this out
– deostroll
Jul 12 '13 at 6:06



tr


td


rowIndex


childNodes



deostroll, I am using Internet Explorer. The rows[rowIndex].tagName propery appears to be null, as it cannot be displayed. Here is my modified code:



The .aspx file:


<%@ Page Title="" Language="C#" MasterPageFile="~/Site1.Master" AutoEventWireup="true"
CodeBehind="StudentList.aspx.cs" Inherits="WebApplication1.WebForm1" %>

<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<script>
function focusRow(id, rowIndex)
var tbl = document.getElementById(id);
var rows = tbl.childNodes[0].childNodes;
alert(rows[rowIndex].tagName);
rows[rowIndex].childNodes[0].focus();

</script>
<br />
<div style="overflow: scroll; height: 400px;">
<asp:GridView ID="StudentList" runat="server" AutoGenerateColumns="False" DataSourceID="DataSource1"
AllowSorting="true" CellPadding="4" DataKeyNames="Email">
<Columns>
<asp:BoundField DataField="LastName" HeaderText="Last" ReadOnly="True" SortExpression="LastName" />
<asp:BoundField DataField="FirstName" HeaderText="First" ReadOnly="True" SortExpression="FirstName" />
<asp:BoundField DataField="MiddleInitial" HeaderText="Middle" ReadOnly="True" SortExpression="MiddleInitial" />
<asp:BoundField DataField="Phone" HeaderText="Phone" ReadOnly="True" SortExpression="Phone" />
<asp:BoundField DataField="Email" HeaderText="Email" ReadOnly="True" SortExpression="Email" />
<asp:BoundField DataField="GPA" HeaderText="GPA" ReadOnly="True" SortExpression="GPA" />
<asp:TemplateField HeaderText="">
<ItemTemplate>
<asp:Button ID="btnEdit1" Text="Edit" AutoPostBack="True" runat="server" OnClick="btnEdit1_OnClick" />
&nbsp
<asp:Button ID="btnDelete" Text="Delete" AutoPostBack="True" runat="server" OnClick="btnDelete_OnClick" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
<SelectedRowStyle BackColor="Black" ForeColor="White" />
</asp:GridView>
</div>
<br />
<br />
Search by Last Name:
<asp:TextBox ID="txtSearch" runat="server"></asp:TextBox>
&nbsp
<asp:Button ID="btnGo" Text="Go" AutoPostBack="True" runat="server" OnClick="btnGo_OnClick" />
<br />
<br />
<asp:Label ID="lbl1" runat="server" Text=""></asp:Label>
<asp:AccessDataSource ID="DataSource1" runat="server" DataFile="~/App_Data/University(2).accdb"
SelectCommand="SELECT [LastName], [FirstName], [MiddleInitial], [Phone], [Email], [GPA]
FROM [Students] ORDER BY [LastName]" DeleteCommand=""></asp:AccessDataSource>
</asp:Content>



The .aspx.cs file:


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

namespace WebApplication1

public partial class WebForm1 : System.Web.UI.Page


protected void Page_Load(object sender, EventArgs e)



protected void btnDelete_OnClick(object sender, EventArgs e)

Button b = (Button)sender;
GridViewRow containingRow = (GridViewRow)b.NamingContainer;
String strEmail = containingRow.Cells[4].Text;
DataSource1.DeleteCommand = "DELETE FROM [CoursesTaken] WHERE [StudentID] = '" + strEmail + "'";
DataSource1.Delete();
DataSource1.DeleteCommand = "DELETE FROM [Students] WHERE [Email] = '" + strEmail + "'";
DataSource1.Delete();
StudentList.DataBind();


protected void btnEdit1_OnClick(object sender, EventArgs e)

Button b = (Button)sender;
GridViewRow containingRow = (GridViewRow)b.NamingContainer;
Session["Email"] = containingRow.Cells[4].Text;
Response.Redirect("~/StudentEdit.aspx");


protected void btnGo_OnClick(object sender, EventArgs e)

int i = 0;
foreach (GridViewRow rowItem in StudentList.Rows)

if (rowItem.Cells[0].Text.ToUpper().StartsWith(txtSearch.Text.ToUpper()))

StudentList.SelectedIndex = i;
ScriptManager.RegisterStartupScript(StudentList, this.GetType(), "highlight",
string.Format("window.onload = function() 2 focusRow('0', 1); 3;", StudentList.ClientID, i + 1, "", ""), true);
break;

i++;






I have it working correctly now. Here is my corrected code:



The .aspx file:


<%@ Page Title="" Language="C#" MasterPageFile="~/Site1.Master" AutoEventWireup="true"
CodeBehind="StudentList.aspx.cs" Inherits="WebApplication1.WebForm1" %>

<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<script>
function focusRow(id, pxlAmount)
var tbl = document.getElementById(id);
dTbl = tbl.parentElement.parentElement;
dTbl.scrollTop = pxlAmount;

</script>
<br />
<div style="overflow: scroll; height: 400px;">
<asp:GridView ID="StudentList" runat="server" AutoGenerateColumns="False" DataSourceID="DataSource1"
AllowSorting="true" CellPadding="4" DataKeyNames="Email" RowStyle-Height="40px">
<Columns>
<asp:BoundField DataField="LastName" HeaderText="Last" ReadOnly="True" SortExpression="LastName" />
<asp:BoundField DataField="FirstName" HeaderText="First" ReadOnly="True" SortExpression="FirstName" />
<asp:BoundField DataField="MiddleInitial" HeaderText="Middle" ReadOnly="True" SortExpression="MiddleInitial" />
<asp:BoundField DataField="Phone" HeaderText="Phone" ReadOnly="True" SortExpression="Phone" />
<asp:BoundField DataField="Email" HeaderText="Email" ReadOnly="True" SortExpression="Email" />
<asp:BoundField DataField="GPA" HeaderText="GPA" ReadOnly="True" SortExpression="GPA" />
<asp:TemplateField HeaderText="">
<ItemTemplate>
<asp:Button ID="btnEdit1" Text="Edit" AutoPostBack="True" runat="server" OnClick="btnEdit1_OnClick" />
&nbsp
<asp:Button ID="btnDelete" Text="Delete" AutoPostBack="True" runat="server" OnClick="btnDelete_OnClick" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
<SelectedRowStyle BackColor="Black" ForeColor="White" />
</asp:GridView>
</div>
<br />
<br />
Search by Last Name:
<asp:TextBox ID="txtSearch" runat="server"></asp:TextBox>
&nbsp
<asp:Button ID="btnGo" Text="Go" AutoPostBack="True" runat="server" OnClick="btnGo_OnClick" />
<br />
<br />
<asp:Label ID="lbl1" runat="server" Text=""></asp:Label>
<asp:AccessDataSource ID="DataSource1" runat="server" DataFile="~/App_Data/University(2).accdb"
SelectCommand="SELECT [LastName], [FirstName], [MiddleInitial], [Phone], [Email], [GPA]
FROM [Students] ORDER BY [LastName]" DeleteCommand=""></asp:AccessDataSource>
</asp:Content>



The .aspx.cs file:


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

namespace WebApplication1

public partial class WebForm1 : System.Web.UI.Page


protected void Page_Load(object sender, EventArgs e)



protected void btnDelete_OnClick(object sender, EventArgs e)

Button b = (Button)sender;
GridViewRow containingRow = (GridViewRow)b.NamingContainer;
String strEmail = containingRow.Cells[4].Text;
DataSource1.DeleteCommand = "DELETE FROM [CoursesTaken] WHERE [StudentID] = '" + strEmail + "'";
DataSource1.Delete();
DataSource1.DeleteCommand = "DELETE FROM [Students] WHERE [Email] = '" + strEmail + "'";
DataSource1.Delete();
StudentList.DataBind();


protected void btnEdit1_OnClick(object sender, EventArgs e)

Button b = (Button)sender;
GridViewRow containingRow = (GridViewRow)b.NamingContainer;
Session["Email"] = containingRow.Cells[4].Text;
Response.Redirect("~/StudentEdit.aspx");


protected void btnGo_OnClick(object sender, EventArgs e)

int i = 0;
foreach (GridViewRow rowItem in StudentList.Rows)

if (rowItem.Cells[0].Text.ToUpper().StartsWith(txtSearch.Text.ToUpper()))

StudentList.SelectedIndex = i;
int iScrollTo = (StudentList.SelectedIndex) * ((int)StudentList.RowStyle.Height.Value); /* RowStyle.Height must be explicitly defined in the opening tag of the GridView */
ScriptManager.RegisterStartupScript(StudentList, this.GetType(), "highlight",
string.Format("window.onload = function() 2 focusRow('0', 1); 3;", StudentList.ClientID, iScrollTo, "", ""), true);
break;

i++;






The problem ended up being something simple: I had not explicitly defined the RowStyle.Height Property of the GridView in its opening tag. Thus, this was being evaluated as "0" during the calculation of the position to scroll to in the div.






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Firebase Auth - with Email and Password - Check user already registered

Dynamically update html content plain JS

How to determine optimal route across keyboard