We use custom a derived GridView and ObjectDataSource control for custom binding, paging, and sorting. While it's working correctly under 3.5 testing under 4.0 shows button commands are not working properly. Included is an eample which I've distilled as
much as possible.
In the example hit Bind Grid for the initial binding, then click 'Next' to advance the page.
In VS 2010 RC when Targetting framework 3.5 everything works as expected.
In VS 2010 RC when Targetting framework 4.0, clicking 'Next' one time works as expected. Clicking 'Next' again fails to raise a paging command.
dbrink
Member
10 Points
13 Posts
Derived GridView button commands only fire once in 4.0
Feb 16, 2010 03:11 PM|LINK
We use custom a derived GridView and ObjectDataSource control for custom binding, paging, and sorting. While it's working correctly under 3.5 testing under 4.0 shows button commands are not working properly. Included is an eample which I've distilled as much as possible.
In the example hit Bind Grid for the initial binding, then click 'Next' to advance the page.
In VS 2010 RC when Targetting framework 3.5 everything works as expected.
In VS 2010 RC when Targetting framework 4.0, clicking 'Next' one time works as expected. Clicking 'Next' again fails to raise a paging command.
<%@ Page Language="C#" AutoEventWireup="false" CodeBehind="Test.aspx.cs" Inherits="Example.TestPage" %>
<%@ Register Assembly="WebApplication1" Namespace="Example" TagPrefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:LinkButton ID="btnBind" runat="server" Text="Bind Grid" OnClick="btnBind_Click" />
<c:GridView ID="gridView" runat="server"
AutoGenerateColumns="false"
DataKeyNames="Id"
OnPageIndexChanging="gridView_PageIndexChanging"
OnSorting="gridView_Sorting"
AllowPaging="true"
AllowSorting="true"
EnableSortingAndPagingCallbacks="false"
>
<Columns>
<asp:BoundField HeaderText="Last" DataField="LastName" SortExpression="LastName" />
<asp:BoundField HeaderText="First" DataField="FirstName" SortExpression="FirstName" />
</Columns>
<EmptyDataTemplate>No data</EmptyDataTemplate>
<PagerTemplate>
<asp:LinkButton ID="btnPrevious" runat="server" CommandName="Page" CommandArgument="Prev" Text="Previous" ValidationGroup="search" />
<asp:LinkButton id="btnNext" runat="server" CommandName="Page" CommandArgument="Next" Text="Next" ValidationGroup="search" />
</PagerTemplate>
</c:GridView>
<c:ObjectDataSource ID="dataSource" runat="server"
TypeName="Example.Person"
DataObjectTypeName="Example.Person"
EnableCaching="false"
DeleteMethod="Delete"
InsertMethod="Insert"
UpdateMethod="Update"
SelectMethod="GetPeople"
EnablePaging="true"
SortParameterName ="sort"
StartRowIndexParameterName="row"
MaximumRowsParameterName="rows"
>
</c:ObjectDataSource>
</div>
</form>
</body>
</html>
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; namespace Example { public class GridView : System.Web.UI.WebControls.GridView { private int? _pageIndex = null; private string _sortExpression = null; private SortDirection? _sortDirection = null; public GridView() : base() { } public override int PageIndex { get { if (!_pageIndex.HasValue) { object value = ViewState["PageIndex"]; if (value != null) { _pageIndex = (int)value; } else { _pageIndex = 0; } } return _pageIndex.Value; } set { if (!Object.Equals(value, ViewState["PageIndex"])) { ViewState["PageIndex"] = value; _pageIndex = value; } } } public override string SortExpression { get { if (_sortExpression == null) { object value = ViewState["SortExpression"]; if (value != null) { _sortExpression = (string)value; } else { _sortExpression = String.Empty; } } return _sortExpression; } } public void SetSortExpression(string value) { if (!Object.Equals(value, ViewState["SortExpression"])) { ViewState["SortExpression"] = value; _sortExpression = value; } } public override SortDirection SortDirection { get { if (!_sortDirection.HasValue) { object value = ViewState["SortDirection"]; if (value != null) { _sortDirection = (SortDirection)value; } else { _sortDirection = SortDirection.Ascending; } } return _sortDirection.Value; } } public void SetSortDirection(SortDirection value) { if (!Object.Equals(value, ViewState["SortDirection"])) { ViewState["SortDirection"] = value; _sortDirection = value; } } } public class ObjectDataSource : System.Web.UI.WebControls.ObjectDataSource { public ObjectDataSource() { } public System.Collections.IEnumerable ExecuteSelect(DataSourceSelectArguments arguments) { return ((ObjectDataSourceView)GetView("DefaultView")).Select(arguments); } } public class Person { public static IList<Person> _people = new List<Person>(); const int TotalPeople = 1000; static Person() { for (int i = 0; i < TotalPeople; i++) { _people.Add(new Person() { Id = i, FirstName = (i % 2) == 0 ? "John" : "Jane", LastName = "Doe " + i, }); } } private int _id; public int Id { get { return _id; } set { _id = value; } } private string _firstName; public string FirstName { get { return _firstName; } set { _firstName = value; } } private string _lastName; public string LastName { get { return _lastName; } set { _lastName = value; } } public static IEnumerable<Person> GetPeople(int row, int rows, string sort) { return _people.OrderBy(p => String.Equals("FirstName", sort) ? p.FirstName : p.LastName).Skip(row).Take(rows).ToList(); } public static Person GetPerson(int id) { return _people.FirstOrDefault(p => p.Id == id); } public static void Update(Person person) { Person existing = GetPerson(person.Id); if (existing == null) { throw new ArgumentOutOfRangeException("Cannot find existing record"); } existing.FirstName = person.FirstName; existing.LastName = person.LastName; } public static void Insert(Person person) { lock (_people) { person.Id = _people.Count; _people.Add(person); } } public static void Delete(Person person) { Delete(person.Id); } public static void Delete(int id) { for (int i = _people.Count - 1; i >= 0; i--) { if (_people[i].Id == id) { _people.RemoveAt(i); return; } } } } public partial class TestPage : System.Web.UI.Page { protected void gridView_Sorting(object sender, GridViewSortEventArgs e) { gridView.SetSortExpression(e.SortExpression); gridView.SetSortDirection(e.SortDirection); gridView.PageIndex = 0; BindGrid(); } protected void gridView_PageIndexChanging(object sender, GridViewPageEventArgs e) { gridView.PageIndex = e.NewPageIndex < 0 ? 0 : e.NewPageIndex; BindGrid(); } protected void btnBind_Click(object sender, EventArgs e) { gridView.PageIndex = 0; BindGrid(); } protected DataSourceSelectArguments CreateDataSourceSelectArguments() { DataSourceSelectArguments arguments = new DataSourceSelectArguments(); int row = (gridView.PageIndex * gridView.PageSize) + 1; int rows = gridView.PageSize; string sortExpression = gridView.SortExpression; if ((gridView.SortDirection == SortDirection.Descending) && !String.IsNullOrEmpty(sortExpression)) { sortExpression = sortExpression + " DESC"; } arguments.SortExpression = sortExpression; arguments.RetrieveTotalRowCount = false; arguments.StartRowIndex = row; arguments.MaximumRows = rows; return arguments; } private void BindGrid() { DataSourceSelectArguments arguments = CreateDataSourceSelectArguments(); System.Collections.IEnumerable results = dataSource.ExecuteSelect(arguments); gridView.DataSource = results; gridView.DataBind(); if (results != null && results.GetEnumerator().MoveNext()) { gridView.BottomPagerRow.Visible = true; } } } }