代码改变世界

编程“方便面”之用户控件

2010-01-30 09:49  邢少  阅读(1828)  评论(12编辑  收藏  举报
学习使用.net已经有数个年头,从使用.net进行cs开发,到现在做Web开发,一直都是想当然的写着、敲着。知道有一天,一个java开发者问我一个问题,我虽然将java语言已经还给母校了,但是还是可以读懂的。在我尝试解决它的问题的时候,发现那哥们无法理解我的想法,他是用eclipse开发java的,java组的一位资深的技术员过来后,对我的解决方法也是不感冒,问我为什么要那么写呢?为什么要那么爱用控件呢?而且不是很认同控件这种将特别功能需求进行封装的编程方式。但是作为一个已经.net语言思路的开发者,我还是很喜欢这些可爱的“控件”家伙的。鄙人感觉它们是体现高级编程语言特点的产物,是高效编程的必要组成。在项目中适度的食用”,还是可以节省大量的代码开发量,并且可以实现页面功能之间的松耦合,使得代码更有条理。这一阵做了几个项目,在项目中对一些问题用“用户控件”做了适度的功能封装,感觉用起来很是方便,但是也感觉用些不足,贴出来互相学习,也希望和园子的朋友对用户控件的使用方式进行交流。
分页问题应该是web开发中的一个常见问题。Gridview控件虽然提供了分页的功能,但是严格的讲,它并不是真正的分页,只是“显示分页”罢了。我做的几个项目都是信息管理系统,数据量比较大,如果用gridview进行分页,在大访问量下实在是“惨”了点,所以就想用存储过程实现分页,每次只是取到本页的20条或者有限的数据。网络的上的存储过程很多,但是实际操作起来也很麻烦,所以就想把分页的功能封装起来,实现一个分页控制器的功能。
先说一下思路吧,我的想法是创建一个分页控制类来控制存储过程的读取,在控件的使用页面传递类似页码、表名称、等适当数量的条件参数,触发更新方法调用存储过程来刷新数据。编写设及的问题有3个:
1、分页控制类的封装,封装那些东西;
2、用户控件与宿主页面的数据交互;
3、分页存储过程;

首先是创建一个用户控件、控件起码要有样子,(记录总共xx 当前第x 首页 上一页 下一页 末页 转到〔〕之类的),简单搞定。至于后台的代码就是逻辑过程了。上一页的操作、下一页等的操作。根据传递的条件,相应的与分页控制类进行交互。

 

 
在页面中,我还放了两个隐藏字段来存储页面必要的两个字段,用来记录分页状态
 
   <asp:HiddenField ID="hdfcurr" runat="server" Value="0" />
      <asp:HiddenField ID="hdfcount" runat="server" Value="0" />

 

从用户控件与宿主页面的数据交互方面先说,delegate〔委托〕可以轻松实现,定义一个回调就可以实现。
   public delegate void DelegateDataBind(DataTable dt);
    
private DelegateDataBind _dataBindEvent;
    
public DelegateDataBind dataBindEvent
    {
        
get { return _dataBindEvent; }
        
set { _dataBindEvent = value; }
    }

 

上述代码定义了一个DelegateDataBind的委托,并实例化,暴露出来。这样就可以方便宿主页面的调用,它传递了一个DataTable类型的参数,它就是分页的结果数据集合。

最后就是分页控制类了,这个应该对大家来说不是什么问题。我是在构造函数中定义参数,string[] 类型存储固定的几个参数。大家也可以用别的方式,反正是怎么方便怎么来。控制类定义 几个方法,上一页、下一页、首页、末页 、转到。还有一个就是初始化数据,代码直接贴出见下:

 

代码
   /// <summary>
    
/// 分页控制类 作者:邢少
    
/// </summary>

    
public class DataPageView
    {
        
private string _tableName;
        
private string _fldName;
        
private int _pageSize;
        
private string _fieldOrder;
        
private string _where;
        
private int _pageCount=1;
        
private int _currPage = 1;
        
private DataSet _ds;
        
private string _sort;
        
private string _strCondition;
        
private string _iD;

        
private int _rowCount;

        
#region 字段
        
/// <summary>
        
/// 数据总行数
        
/// </summary>
        public int RowCount
        {
            
get { return _rowCount; }
            
set { _rowCount = value; }
        }

        
/// <summary>
        
/// 主键
        
/// </summary>
        public string ID
        {
            
get { return _iD; }
            
set { _iD = value; }
        }
        
/// <summary>
        
/// 查询条件,不需where
        
/// </summary>
        public string StrCondition
        {
            
get { return _strCondition; }
            
set { _strCondition = value; }
        }
        
/// <summary>
        
/// -排序方法,0为升序,1为降序(如果是多字段排列Sort指代最后一个排序字段的排列顺序(最后一个排序字段不加排序标记
        
/// </summary>
        public string Sort
        {
            
get { return _sort; }
            
set { _sort = value; }
        }
/// <summary>
        
/// 数据集
        
/// </summary>
        public DataTable DataTableView
        {
            
get
            {
                DataInitializtion();
                
return _ds.Tables[0];
            }
        }
        
/// <summary>
        
/// 分页显示的表名
        
/// </summary>
        public string TableName
        {
            
get { return _tableName; }
            
set { _tableName = value; }
        }
        
/// <summary>
        
/// 要显示的字段列表
        
/// </summary>
        public string FfldName
        {
            
get { return _fldName; }
            
set { _fldName = value; }
        }
        
/// <summary>
        
/// 每页显示的数据行
        
/// </summary>
        public int PageSize
        {
            
get { return _pageSize; }
            
set { _pageSize = value; }
        }
        
/// <summary>
        
/// 以逗号分隔的排序字段列表,可以指定在字段后面指定DESC/ASC用于指定排序顺序
        
/// </summary>
        public string FieldOrder
        {
            
get { return _fieldOrder; }
            
set { _fieldOrder = value; }
        }
        
/// <summary>
        
/// 查询条件
        
/// </summary>
        public string Where
        {
            
get { return _where; }
            
set { _where = value; }
        }
        
/// <summary>
        
/// 总页数
        
/// </summary>
        public int PageCount
        {
            
get { return _pageCount; }
        }
        
/// <summary>
        
/// 页数信息
        
/// </summary>
        public string TablePageInfo
        {
            
get
            {
                
return string.Format("共 {0} 条记录, 当前第 {1}/{2} 页 每页{3}条记录", RowCount, _currPage <= _pageCount ? _currPage.ToString() : _pageCount.ToString(), _pageCount > 0 ? _pageCount.ToString() : "0", _pageSize);
            }
        }

        
public int CurrPgae
        {
            
get { return _currPage; }
        }

        
#endregion

        
public DataPageView(string[] list)
        {
            _iD 
= list[1];
            _fldName 
= list[2];
            _pageSize 
=20;
            _strCondition 
= list[3];
            _tableName 
= list[0];
            _sort 
= list[5];
            _fieldOrder 
= list[6];
            _currPage 
= Convert.ToInt32(list[4]);
        }

        
#region Methods
        
/// <summary>
        
/// 末页
        
/// </summary>
        public void Last()
        {
            
if (_pageCount == 0)
                _currPage 
= 1;
            
else
                _currPage 
= Convert.ToInt32(_pageCount);
           
        }
        
/// <summary>
        
/// 首页
        
/// </summary>
        public void Home()
        {
            _currPage 
= 1;
           
        }
        
/// <summary>
        
/// 上页
        
/// </summary>
        public void Up()
        {
            
if (_currPage >1)
                _currPage
--;

        }
        
/// <summary>
        
/// 下页
        
/// </summary>
        public void Down()
        {
            
if(_currPage<_pageCount)
                _currPage
++;
         
        }

        
public void Goto(string currPage)
        {
            _currPage 
= Convert.ToInt32(currPage);
        }

        
#endregion

        
private void DataInitializtion()
        {
            SqlParameter[] parameters 
= {
                    
new SqlParameter("@psTblName", DbType.String), 
                
new SqlParameter("@psStrGetFields", DbType.String),
                
new SqlParameter("@psPageSize", DbType.Int32),
                
new SqlParameter("@psPageIndex ", DbType.Int32),
                
new SqlParameter("@psOrderType", DbType.Byte), 
                
new SqlParameter("@psStrWhere", DbType.String), 
                
new SqlParameter("@psFieldName", DbType.String),
                
new SqlParameter("@rsPageCount", DbType.Int32),
                
new SqlParameter("@rsRecordCount", DbType.Int32)
                    };
            parameters[
0].Value = _tableName;
            parameters[
1].Value = _fldName;
            parameters[
2].Value = _pageSize;
            parameters[
3].Value = _currPage > 0 ? _currPage : 1;
            parameters[
4].Value = _sort;
            parameters[
5].Value = _strCondition;
            parameters[
6].Value = _fieldOrder;
            parameters[
7].Direction = ParameterDirection.Output; ;
            parameters[
8].Direction = ParameterDirection.Output; ;

            _ds 
= HebHX.DBUtility.DbHelperSQL.RunProcedure("sp_general_pagination", parameters, "List");

            _pageCount 
= Convert.ToInt32(parameters[7].Value);
            _rowCount 
= Convert.ToInt32(parameters[8].Value);
            
if (_currPage > _pageCount) _currPage = _pageCount;
        }
    }

 

 

最后就是整一个存储过程,我这个也是从网络上copy的。随便网网吧,满地都是。

三个主要的问题都已经解决。最后看一下调用:

 

代码
        if (ViewState["where"== null) ViewState["where"= "";
        
//绑定信息
        DataPageView1.PageField = new string[] { "PTPosts""PosID""*", ViewState["where"].ToString(), "1""0""PosID" };
        DataPageView1.dataBindEvent 
= delegate(DataTable dt) { rptPosts.DataSource = dt; rptPosts.DataBind(); };

 

viewstate 存储的是页面的条件,主要是考虑比如在查询情况下的分页,回传的时候可以存储查询条件。

最下面就是对页面的数据控件的绑定。

 

现在一个分页控制用户控件就整理好了。贴出分页效果

应该还是很好用的,我在2个项目中都用到了它,很方便。现在贴出来与大家交流。我一直有想法想将该控件封装成为web控件,现在准备着手,为了想把它弄的更通用一些所以想准备的更充分些,好了就说这么多吧。