[小技巧]让你的GridView支持IQueryable,并自动实现真分页

8/10/2015来源:ASP.NET技巧人气:4817

[小技巧]让你的GridView支持IQueryable,并自动实现真分页

众所周知,asp.net自带的GridView在自带分页方面设计得很2,因为它是假分页,即内存分页。而且它不智能支持强大的Iqueryable。

但这表明微软忽略了现实中的分页需求吗?答案应该不是,我想也不是。

那么,通过什么方式可以达到真分页的效果呢?使用Asp.Net自带的3种DataSource(objectdatasource, entitydatasource, linqdatasource)。 三种datasource各有所长。

但这样做还是有些麻烦呀……

朋友有一个项目,之前数据少,没有考虑过假分页带来的隐患,现在项目也做大了,数据也大了,问题也出来了,怎么办可以实现最少改动呢?废话不多说,直接上代码:

1 自定义一个PageGridView

using System;using System.Collections;using System.Collections.Generic;using System.Data;using System.Linq;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;using System.Reflection;namespace DGVTest{    public class PagingGridView : GridView    {        public PagingGridView()        {                    }        PRivate IQueryable querableData;        public override Object DataSource         {            get            {                return base.DataSource;            }            set            {                if (value is IQueryable)                {                    querableData = (IQueryable)value;                    ObjectDataSource ods = new ObjectDataSource();                                   ods.ID = "ods_" + this.ID;                    ods.EnablePaging = this.AllowPaging;                    // This must be the full name of the class                    ods.TypeName = "DGVTest.IQueryableAdapter";                    ods.SelectMethod = "GetData";                    ods.SelectCountMethod = "GetCount";                    ods.StartRowIndexParameterName = "startRowIndex";                    ods.MaximumRowsParameterName = "pageSize";                                        ods.EnableViewState = false;                    ods.ObjectCreating += (o,e)=> e.ObjectInstance = new IQueryableAdapter(querableData);                    base.DataSource = ods;                    if (AllowPaging)                    {                        PageIndexChanging += (o, gpe) =>                        {                            PageIndex = gpe.NewPageIndex;                            DataBind();                        };                    }                    if (AllowSorting)                    {                        //---if want to implement sorting...                    }                }                else                {                    base.DataSource = value;                }            }        }     }    public class IQueryableAdapter     {        private IQueryable _data;        private int _totalCount;        public IQueryableAdapter(IQueryable data)        {            _data = data;            _totalCount = (int)GetExtMethod("Count", _data ).Invoke(null, new object[] { _data });                     }        public object GetData()         {            return _data;        }        public int GetCount()         {            return _totalCount;         }        public object GetData(int startRowIndex, int pageSize)        {            var enumResult = GetExtMethod("Skip", _data).Invoke(null, new object[] { _data, startRowIndex });            return GetExtMethod("Take", _data ).Invoke(null, new object[] { enumResult, pageSize });        }        private MethodInfo GetExtMethod(string methodName,object obj )        {            var genType = obj.GetType().GetGenericArguments()[0];            return typeof(System.Linq.Queryable)                .GetMethods(BindingFlags.Public | BindingFlags.Static)                .First(m => m.Name == methodName)                .MakeGenericMethod(genType);        }    }     }

2 把这个新的GridView引入原项目

一般的做法是在页面上添加引用符:

<%@ Register Assembly="DGVTest" Namespace="DGVTest" TagPrefix="juyee" %>

然后把原GridView的前缀改了:

 <juyee:PagingGridView ID="GridView1" runat="server" AllowPaging="True" AllowSorting="True"></juyee:PagingGridView>

但每个页面都加引用命令,还是很麻烦的。这可以通过在config解决:

  <system.web>    <pages>      <controls>        <add tagPrefix="juyee" namespace="DGVTest"              assembly="DGVTest" />      </controls>    </pages>  </system.web>

有了这个,就不用每个页面加引用命令啦。至于替换gridview的声明嘛,可以用ctrl+F。

3 Code-Behind

现在可以直接把IQueryable类型的对象做为新View的数据源啦。值得一提的是,一定要orderby一下哟,不然执行IQueryable.Skip时会报错。

            var ds= from t in new testdbEntities().People                    orderby t.Name                    select t;             GridView1.DataSource =ds;            GridView1.DataBind();

至此问题解决~赶快试试吧。