webabcd - 专注于asp.net

ASP.NET
从现在开始 一切都不晚
posts - 152, comments - 4207, trackbacks - 346, articles - 0
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理
GridView既强大又好用。为了让它更强大、更好用,我们来写一个继承自GridView的控件。
[索引页]
[源码下载]


扩展GridView控件(0) - 基本架构、增加事件和要点汇总


作者:webabcd


介绍
扩展GridView控件时采用的基本架构;为GridView控件增加自定义事件;扩展GridView控件时的要点汇总


1、基本架构
定义一个抽象类,每个实现扩展功能的类都要实现这个抽象类
using System;
using System.Collections.Generic;
using System.Text;

namespace YYControls.SmartGridViewFunction
{
    
/// <summary>
    
/// 扩展功能类,抽象类
    
/// </summary>

    public abstract class ExtendFunction
    
{
        
/// <summary>
        
/// SmartGridView对象变量
        
/// </summary>

        protected SmartGridView _sgv;

        
/// <summary>
        
/// 构造函数
        
/// </summary>

        public ExtendFunction()
        
{
            
        }


        
/// <summary>
        
/// 构造函数
        
/// </summary>
        
/// <param name="sgv">SmartGridView对象</param>

        public ExtendFunction(SmartGridView sgv)
        
{
            
this._sgv = sgv;
        }


        
/// <summary>
        
/// SmartGridView对象
        
/// </summary>

        public SmartGridView SmartGridView
        
{
            
get return this._sgv; }
            
set this._sgv = value; }
        }


        
/// <summary>
        
/// 实现扩展功能
        
/// </summary>

        public void Complete()
        
{
            
if (this._sgv == null)
            
{
                
throw new ArgumentNullException("SmartGridView""扩展功能时未设置SmartGridView对象");
            }

            
else
            
{
                Execute();
            }

        }


        
/// <summary>
        
/// 扩展功能的具体实现
        
/// </summary>

        protected abstract void Execute();
    }

}


如果需要为GridView扩展功能的话,只要继承这个类,并重写其Execute()方法即可

调用各个扩展功能对象的时候,可以先根据条件把需要的对象添加到List<ExtendFunction>,然后遍历它,并设置ExtendFunction的SmartGridView属性,调用ExtendFunction的Complete()方法即可


2、增加事件
RowDataBound是一个比较常用的事件,往往我们会在其内判断一下Row的RowType是否是DataRow,所以我们完全可以增加一个RowDataBoundDataRow事件(RowDataBound事件中,当Row.RowType为DataControlRowType.DataRow的时候触发)。我们还可以根据需要为GridView增加其它的事件,接下来以为GridView增加RowDataBoundDataRow事件为例说一下如何实现。
i) 添加delegate
using System;
using System.Collections.Generic;
using System.Text;

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

namespace YYControls
{
    
/// <summary>
    
/// SmartGridView类的委托部分
    
/// </summary>

    public partial class SmartGridView
    
{
        
/// <summary>
        
/// RowDataBoundDataRow事件委托
        
/// </summary>
        
/// <remarks>
        
/// RowDataBound事件中的DataControlRowType.DataRow部分
        
/// </remarks>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>

        public delegate void RowDataBoundDataRowHandler(object sender, GridViewRowEventArgs e);
    }

}


ii) 添加event
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;

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

namespace YYControls
{
    
/// <summary>
    
/// SmartGridView类的事件部分
    
/// </summary>

    public partial class SmartGridView
    
{
        
private static readonly object rowDataBoundDataRowEventKey = new object();
        
/// <summary>
        
/// RowDataBound事件中的DataControlRowType.DataRow部分
        
/// </summary>

        [Category("扩展")]
        
public event RowDataBoundDataRowHandler RowDataBoundDataRow
        
{
            add 
{ Events.AddHandler(rowDataBoundDataRowEventKey, value); }
            remove 
{ Events.RemoveHandler(rowDataBoundDataRowEventKey, value); }
        }

        
/// <summary>
        
/// 触发RowDataBoundDataRow事件
        
/// </summary>
        
/// <param name="e"></param>

        protected virtual void OnRowDataBoundDataRow(GridViewRowEventArgs e)
        
{
            RowDataBoundDataRowHandler handler 
= Events[rowDataBoundDataRowEventKey] as RowDataBoundDataRowHandler;

            
if (handler != null)
            
{
                handler(
this, e);
            }

        }

    }

}


iii) 重写GridView的OnRowDataBound
        /// <summary>
        
/// OnRowDataBound
        
/// </summary>
        
/// <param name="e">e</param>

        protected override void OnRowDataBound(GridViewRowEventArgs e)
        
{
            DataControlRowType rowType 
= e.Row.RowType;

            
if (rowType == DataControlRowType.DataRow)
            
{
                OnRowDataBoundDataRow(e);
            }


            
base.OnRowDataBound(e);
        }



3、要点汇总
a) 嵌入资源
设置资源文件的“生成操作”为“嵌入的资源”
定义在程序集中启用嵌入式资源的元数据属性
[assembly: System.Web.UI.WebResource("YYControls.SmartGridView.Resources.ScriptLibrary.js""text/javascript")]
使用嵌入资源
if (!this.Page.ClientScript.IsClientScriptIncludeRegistered(this.GetType(), "yy_sgv_ScriptLibrary"))
{
    
// 注册所需脚本
    this.Page.ClientScript.RegisterClientScriptInclude
    (
        
this.GetType(),
        
"yy_sgv_ScriptLibrary",
        
this.Page.ClientScript.GetWebResourceUrl
        (
            
this.GetType(), "YYControls.SmartGridView.Resources.ScriptLibrary.js"
        )
    );
}

// this.Page.ClientScript.RegisterClientScriptResource(this.GetType(), "YYControls.SmartGridView.ScriptLibrary.js");

b) Debug和Release使用不用的资源
#if DEBUG
[assembly: System.Web.UI.WebResource(
"YYControls.SmartGridView.Resources.ScriptLibraryDebug.js""text/javascript")]
#else
[assembly: System.Web.UI.WebResource(
"YYControls.SmartGridView.Resources.ScriptLibrary.js""text/javascript")]
#endif

c) 为自定义控件添加图标
[System.Drawing.ToolboxBitmap(typeof(YYControls.Resources.Icon), "SmartGridView.bmp")]

d) 设置自定义控件的标记前缀
[assembly: TagPrefix("YYControls""yyc")]

e) 常用元数据
Browsable - 指定一个属性 (Property) 或事件是否应显示在“属性”窗口中
Description - 指定属性 (Property) 或事件的说明
Category - 给属性或事件分组的类别的名称
NotifyParentProperty - 指示当此属性应用到的属性的值被修改时将通知父属性
DefaultValue - 指定属性 (Property) 的默认值
Editor - 指定用来更改属性的编辑器
ToolboxItem - 表示工具箱项的属性
ToolboxData - 指定当从 Microsoft Visual Studio 等工具中的工具箱拖动自定义控件时为它生成的默认标记
TypeConverter - 指定用作此属性所绑定到的对象的转换器的类型(一般是[TypeConverter(typeof(ExpandableObjectConverter))])
DesignerSerializationVisibility - 指定在设计时序列化组件上的属性 (Property) 时所使用的持久性类型
PersistenceMode - 定义指定如何将 ASP.NET 服务器控件属性 (Property) 或事件保持到 ASP.NET 页的元数据特性 (Attribute)
ParseChildren - 指示页分析器应如何处理页上声明的服务器控件标记中嵌套的内容
PersistChildren - 指示在设计时服务器控件中包含的嵌套内容是与控件对应,还是作为服务器控件的属性 (Property)

f) 复合属性
定义一个实体类,复合属性就是这个实体类对象,在复合属性上增加元数据
[
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
PersistenceMode(PersistenceMode.InnerProperty)
]

g) 集合属性
定义一个继承自CollectionBase的类,集合属性就是这个类的对象,在集合属性上增加元数据
[
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
PersistenceMode(PersistenceMode.InnerProperty)
]


OK
[源码下载] 

Feedback

#1楼    回复  引用  查看    

2007-08-08 09:12 by 老夫子系      
好东西,谢谢!

#2楼    回复  引用  查看    

2007-08-08 10:28 by Clingingboy      
非常好,后端差不多就这样了,涉及到比较多的是数据的交互.接着的事情还得javascript帮忙

#3楼    回复  引用    

2007-08-08 10:50 by anhwa [未注册用户]
http://www.codeplex.com/EnhancedGridView

#4楼    回复  引用    

2007-08-08 11:15 by askyes [未注册用户]
太强了,什么时候能看懂你写的这个东西我也就牛了

#5楼 [楼主]   回复  引用  查看    

2007-08-08 11:22 by webabcd      
@老夫子系
:)
不谢

@Clingingboy
嗯,是这样的

@anhwa
那个东东扩展的功能好像不多

@askyes
踏踏实实地看,还是挺容易就能看懂的

#6楼    回复  引用  查看    

2007-08-08 14:16 by 细节决定成败,习惯决定未来      
不错,好东西,
正式版本多久更新一次?
建议加上换页选择的功能.像gmail一样.换页时,能记住上页选择的.

#7楼 [楼主]   回复  引用  查看    

2007-08-08 18:32 by webabcd      
@细节决定成败,习惯决定未来
有bug肯定会马上修改、更新
另外会不定时增加新的功能

嗯,很常用的功能,下次加上

#8楼    回复  引用    

2007-08-08 21:36 by kisskiki [未注册用户]
相当喜欢看webabcd的控件系列翻译,不过似乎现在更新比以前慢了
我望眼欲穿啊:)

#9楼    回复  引用    

2007-08-08 22:55 by 黑白 [未注册用户]
不得不佩服博主,太强了

#10楼 [楼主]   回复  引用  查看    

2007-08-09 07:48 by webabcd      
@kisskiki
嗯,最近有些懒了
准备复出中……

#11楼 [楼主]   回复  引用  查看    

2007-08-09 07:49 by webabcd      
@黑白
:)
抬举了

#12楼    回复  引用  查看    

2007-08-09 13:26 by jasonoiu      
不好意思,可能是个肤浅的问题,在第一个定义抽象类中,要定义SmartGridView变量:
//// <summary>
/// SmartGridView对象变量
/// </summary>
protected SmartGridView _sgv;
但是,SmartGridView事先没有定义,不知道怎么回事,请指点!

#13楼 [楼主]   回复  引用  查看    

2007-08-09 15:47 by webabcd      
@jasonoiu
你需要写一个SmartGridView类,它继承自GridView,所以可以扩展它
代码太多,不能全贴出来

兄弟可以下一下源代码看一看

#14楼    回复  引用    

2007-08-10 21:42 by grass [未注册用户]
如果我想应用你的翻页按钮,而触发自己的翻页事件呢??
也就是说我想自定义翻页!!

#15楼 [楼主]   回复  引用  查看    

2007-08-13 07:40 by webabcd      
@grass
可以阿
注意一下LinkButton的
CommandName和CommandArgument

#16楼    回复  引用    

2007-08-13 17:15 by zjj [未注册用户]
厉害.向你学习!

#17楼 [楼主]   回复  引用  查看    

2007-08-13 17:54 by webabcd      
@zjj
:)
大家多交流,互相学习

#18楼    回复  引用  查看    

2007-08-30 22:10 by 旌浪      
@webabcd
征得您的同意,我將SmartGridView轉成了VB版的了。源碼請至鏈接處下載,由於水平有限,只是簡單的語法轉換,並沒有加入vb的特性。

#19楼 [楼主]   回复  引用  查看    

2007-08-31 08:00 by webabcd      
@旌浪
多谢兄弟的热心
已把你的作品的链接添加至了SmartGridView的索引页
http://www.cnblogs.com/webabcd/archive/2007/02/04/639830.html

#20楼    回复  引用    

2007-09-04 13:10 by 清风 [未注册用户]
看不懂这东西!呜呜~~~~

#21楼 [楼主]   回复  引用  查看    

2007-09-04 18:36 by webabcd      
@清风
耐心看看,其实还是挺简单的

#22楼    回复  引用  查看    

2007-09-29 16:45 by highmayor      
首先表示对博主的敬意!
请问以下下面这句是作什么用的:
// for asp.net ajax
this.Page.ClientScript.RegisterStartupScript(
this.GetType(),
"yy_sgv_ScriptLibrary_ajax",
"if (typeof(Sys) != 'undefined') Sys.WebForms.PageRequestManager.getInstance().add_endRequest(function endRequestHandler(sender, e){yy_sgv_ccListener();yy_sgv_crListener();});",
true);

是不是有关ajax功能的?怎么用呢?我在放有SmartGridView的页面的源代码怎么没有找到“yy_sgv_ScriptLibrary_ajax”这个函数呢?

#23楼    回复  引用  查看    

2007-09-29 18:01 by highmayor      
再请教两个问题:
1.Common类并没有从IAttributeAccessor接口继承,为什么?Attribute.cs里面的SetAttribute有什么作用?

2。helper里面的SmartGridView.cs是做什么用的?

#24楼 [楼主]   回复  引用  查看    

2007-09-30 07:55 by webabcd      
@highmayor
那句话是为了使扩展的功能支持asp.net ajax的
“yy_sgv_ScriptLibrary_ajax”不是函数名,而是key

1、为控件添加属性用的
2、和GridView有关的一些常用的方法

#25楼    回复  引用  查看    

2007-09-30 08:34 by highmayor      
哦,我明白了,由于gridview已经实现了IAttributeAccessor接口,所以SmartGridView不需要再继承IAttributeAccessor接口了,对于SetAttribute ,MSDN是这样解释的:
Implement the SetAttribute method for the control. When
this method is called from a page, the control's properties
are set to values defined in the page.
我不懂的是为什么一些属性用Attribute.cs里面的SetAttribute来设置,一些属性却是下面这么设置呢?
public virtual string MergeCells
{
get { return _mergeCells; }
set { _mergeCells = value; }
}

请赐教,谢谢!

#26楼 [楼主]   回复  引用  查看    

2007-09-30 10:19 by webabcd      
@highmayor
SetAttribute是用来设置控件的在客户端所呈现的html元素的属性

private string _mergeCells;
public virtual string MergeCells
{
get { return _mergeCells; }
set { _mergeCells = value; }
}
是c#里属性的标准写法

#27楼    回复  引用  查看    

2007-09-30 10:48 by highmayor      
这两者有什么不同呢?

#28楼    回复  引用