ASP.NET 2.0数据绑定控件的自定义集合

开发 后端
本文介绍ASP.NET 2.0数据绑定控件的自定义集合。ListControl 是一个过于专用的类,它以不受您控制的固定方式执行数据绑定。

ASP.NET 2.0数据绑定控件:管理自定义集合

ListControl 是一个过于专用的类,它以不受您控制的固定方式执行数据绑定 — 除非您重写诸如 PerformSelect、OnDataBinding 和 PerformDataBinding 之类的方法。它还提供了预定义的 Items 集合属性。让我们在 ASP.NET 2.0 中的更低级别处理数据绑定,并且设计具有下列功能的 ButtonList 控件:

◆使用自定义集合类来保留组成项

◆用自定义方式管理视图状态

ButtonList 控件是另一个为每个绑定数据项输出按钮的列表控件。您可以让它从 ListControl 继承;而且,您可以获得 HeadlineList 的源代码,将 Label 替换为 Button,而它仍然应当正常工作。这一次,我将采用一种不同的方法来说明 DataBoundControl 的行为。为简单起见,我仍将跳过 IRepeatInfoUser 接口。

  1. public class ButtonList : System.Web.UI.WebControls.DataBoundControl  
  2. {  
  3.    :  
  4. }  

标题和命令名称表现了每个按钮的性质。该信息是通过几个自定义属性(如 DataTextField 和 DataCommandField)从绑定数据源中获得的。您可以容易地添加类似的属性,以提供数据绑定工具提示,甚至提供 URL。

  1. public virtual string DataCommandField  
  2. {  
  3.    get 
  4.    {  
  5.       object o = ViewState["DataCommandField"];  
  6.       if (o == null)  
  7.          return "";  
  8.       return (string)o;  
  9.    }  
  10.    set { ViewState["DataCommandField"] = value; }  
  11. }  

所发现的有关每个绑定按钮的所有信息都被填充到一个通过 Items 属性公开的自定义对象集合中。(请注意,Items 只是该属性的标准、惯用而任意的名称。)

  1. [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]  
  2. [PersistenceMode(PersistenceMode.InnerProperty)]  
  3. public virtual ButtonItemCollection Items  
  4. {  
  5.    get 
  6.    {  
  7.       if (_items == null)  
  8.       {  
  9.          _items = new ButtonItemCollection();  
  10.          if (base.IsTrackingViewState)  
  11.             _items.TrackViewState();  
  12.       }  
  13.       return _items;  
  14.    }  
  15. }  

Items 集合是自定义 ButtonItemCollection 类的实例 — ButtonItem 对象的集合。ButtonItem 类只是存储了有关绑定按钮的关键信息 — Text 和 CommandName 属性,外加几个构造函数以及 ToString 方法。ButtonItem 类是作为普通列表控件的 ListItem 类的对等物。下面是一个示例。

  1. public class ButtonItem  
  2. {  
  3.    private string _text;  
  4.    private string _command;  
  5.  
  6.    public ButtonItem(string text, string command) {  
  7.       _text = text;  
  8.       _command = command;  
  9.    }  
  10.    public string Text {  
  11.       get {return _text;}  
  12.       set {_text = value;}  
  13.    }  
  14.    public string CommandName {  
  15.       get { return _command; }  
  16.       set { _command = value; }  
  17.    }  
  18.    public override string ToString() {  
  19.       return "Button [" + Text + "]";  
  20.    }  
  21. }  
  22.  

现在,如何创建 ButtonItem 对象的集合呢?在 ASP.NET 1.x 中,您必须生成一个从 CollectionBase 继承的自定义集合类,并且起码重写几个方法。然而,自定义集合只是围绕 ArrayList 对象的包装而已,在访问速度方面并没有任何真正的优势。实际上,仍然需要进行转换。.NET 2.0 中的泛型提供了真正的转折点。要生成 ButtonItem 对象集合,您需要以下代码:

  1. public class ButtonItemCollection : Collection < ButtonItem>  
  2. {  
  3. }  

并且,它的性能也会更好,因为编译器在幕后完成了某些工作。ButtonList 控件只需要两个被重写的方法:Render 和 PerformDataBinding。Render 假定 Items 集合被填充;因此,它只是进行迭代并输出标记代码。

  1. protected override void Render(HtmlTextWriter writer)  
  2. {  
  3.    for(int i=0; i< } btn.RenderControl(writer); btn.CommandName="item.CommandName;" btn.Text="item.Text;" Button(); btn="new" Button item="Items[i];" ButtonItem { i++)>  

ASP.NET 2.0数据绑定控件:Items集合的重要性

Items 集合为什么如此重要?它可以帮助您获得两个结果。首先,您可以用手动添加的项填充该列表控件。其次,一旦在视图状态中持久保存该集合,您就可以在回发时重新生成该控件的用户界面,而无须绑定到数据。在进行数据绑定时,Items 集合是在何处以及由谁填充的呢?这需要用到 PerformDataBinding。该方法获得一个可枚举的数据列表(无论原始数据源是什么)并使用它来填充 Items 集合。

  1. protected override void PerformDataBinding(IEnumerable dataSource)  
  2. {  
  3.    base.PerformDataBinding(dataSource);  
  4.    string textField = DataTextField;  
  5.    string commandField = DataCommandField;  
  6.  
  7.    if (dataSource != null) {  
  8.    foreach (object o in dataSource)  
  9.    {  
  10.       ButtonItem item = new ButtonItem();  
  11.       item.Text = DataBinder.GetPropertyValue(o, textField, null);  
  12.       item.CommandName = DataBinder.GetPropertyValue(o,   
  13.                                              DataCommandField, null);  
  14.       Items.Add(item);  
  15.    }   
  16.    }  
  17. }  
  18.  

每当需要进行数据绑定时,该方法都能够确保 Items 集合被填充。在回发时会发生什么?在这种情况下,必须根据视图状态重新构建 Items 集合。您可以通过 IStateManager 接口上的方法赋予自定义集合类这一能力。以下为该接口的关键方法:

  1. public void LoadViewState(object state)  
  2. {  
  3.    if (state != null) {  
  4.       Pair p = (Pair) state;  
  5.       Clear();  
  6.       string[] rgText = (string[])p.First;  
  7.       string[] rgCommand = (string[])p.Second;  
  8.  
  9.       for (int i = 0; i < rgText.Length; i++)  
  10.          Add(new ButtonItem(rgText[i], rgCommand[i]));  
  11.    }  
  12. }  
  13.  
  14. public object SaveViewState()  
  15. {  
  16.    int numOfItems = Count;  
  17.    object[] rgText = new string[numOfItems];  
  18.    object[] rgCommand = new string[numOfItems];  
  19.  
  20.    for (int i = 0; i < numOfItems; i++) {  
  21.       rgText[i] = this[i].Text;  
  22.       rgCommand[i] = this[i].CommandName;  
  23.    }  
  24.  
  25.    return new Pair(rgText, rgCommand);  
  26. }  
  27.  

该类使用一个 Pair 对象(一种经过优化的 2 位置数组)将自身序列化为视图状态。您需要创建两个对象数组,以便保留每个按钮的文本和命令名称。这两个数组随后被成对打包并插入到该视图状态中。当还原该视图状态时,会将该数组对拆包,并且使用先前存储的信息重新填充 Items 集合。使用该方法要比使 ButtonItem 类可序列化更可取,因为传统的二进制格式化程序的性能(在空间和时间这两个方面)更差。

然而,向集合中添加视图状态支持还不够。还必须增强 ButtonList 控件以利用集合的序列化功能。您可以重写控件类上的 LoadViewState 和 SaveViewState。

  1. protected override void LoadViewState(object savedState)  
  2. {  
  3.    if (savedState != null) {  
  4.       Pair p = (Pair) savedState;  
  5.       base.LoadViewState(p.First);  
  6.       Items.LoadViewState(p.Second);  
  7.    }  
  8.    else 
  9.       base.LoadViewState(null);  
  10. }  
  11.  
  12. protected override object SaveViewState()  
  13. {  
  14.    object baseState = base.SaveViewState();  
  15.    object itemState = Items.SaveViewState();  
  16.    if ((baseState == null) && (itemState == null))  
  17.       return null;  
  18.    return new Pair(baseState, itemState);  
  19. }  
  20.  

控件的视图状态由两个元素组成:默认控件的视图状态以及 Items 集合。这两个对象被打包到 Pair 对象中。除了 Pair 对象以外,您还可以使用 Triplet 对象(包含三个对象的数组),或者使用 Pair 或 Triplet 对组成任意数量的对象。

以这种方式设计的自定义集合还可以在设计时满足需要。Visual Studio 2005 中嵌入的默认集合编辑器可以识别该集合并弹出如图 3 所示的对话框。

设计时的 ButtonList Items 集合 

ASP.NET 2.0数据绑定控件:设计时的 ButtonList Items 集合

值得说明的是,在 ASP.NET 2.0 中,某些数据绑定控件使您可以将数据绑定项与以编程方式通过 Items 集合添加的项分开。布尔型的 AppendDataBoundItems 属性用于控制该控件的编程接口的这一方面。该属性在 ListControl(而非 DataBoundControl)上定义,并且默认为 false。

【编辑推荐】

  1. 列表控件示例:HeadlineList
  2. ASP.NET 2.0数据绑定机制:生成控件
  3. ASP.NET 2.0数据绑定的发展简述
  4. 概述ASP.NET调用Excel进程
  5. ASP.NET开发技巧之Theme功能浅析
责任编辑:yangsai 来源: MSDN
相关推荐

2009-08-05 17:43:48

ASP.NET 2.0

2009-08-10 14:16:59

ASP.NET自定义控

2009-07-28 09:32:41

ASP.NET自定义控

2009-08-06 17:13:56

ASP.NET自定义控

2011-04-19 10:33:16

ASP.NET自定义控

2009-07-31 10:23:09

ASP.NET源码DateTimePic

2009-08-06 09:18:01

ASP.NET自定义控ASP.NET控件开发

2009-07-22 17:21:27

ASP.NET 2.0

2009-07-28 14:06:28

ASP.NET 2.0

2009-08-01 12:00:15

ASP.NET服务器自ASP.NET服务器ASP.NET

2009-08-05 17:26:25

ASP.NET 2.0

2011-05-19 10:16:27

ASP.NET

2009-08-07 15:34:15

ASP.NET数据绑定

2009-08-06 17:52:45

ASP.NET控件开发自定义控件

2009-07-24 17:15:52

SiteMapData

2009-08-07 11:12:58

ASP.NET控件开发

2009-07-27 09:01:44

ObjectDataS

2009-08-03 18:15:05

ASP.NET数据绑定

2009-08-04 13:35:16

ASP.NET自定义样

2009-08-07 15:45:26

ASP.NET复合控件数据绑定
点赞
收藏

51CTO技术栈公众号