开发模板化数据绑定控件

对于数据绑定控件的开发,其主要的要点如下:

1、  定义控件实现INamingContainer接口;

 

2、  对于基于模板的数据绑定控件还需要实现模板属性;

 

3、  实现有关数据绑定的内容,包括建立DataSource和DataBind方法等;

 

4、  使用数据源或者ViewState数据创建子控件层次结构。

 

以上四点是开发基于模板的数据绑定控件的基本要点,在VS.NET中提供的比较典型的模板数据绑定控件就是DATAGRID了,下面我们来实际做一个例子实现类似与DATAGRID的模板化绑定的效果。

 

例子共包括两个主要文件:实现模板容器的Item.cs文件和实现控件主体的DataBindTmp.cs文件,两个文件的代码如下:

Item.cs
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;

namespace Hdkj.Ying
{
 /// <summary>
 /// Item 的摘要说明。
 /// </summary>
 public class ItemTmp : System.Web.UI.WebControls.TableCell,INamingContainer
 {
  private object _dataItem;

  public ItemTmp(object dataItem)
  {
   _dataItem = dataItem;
  }

  public override ControlCollection Controls
  {
   get
   {
    EnsureChildControls();
    return base.Controls;
   }
  }

  public object DataItem
  {
   get{return _dataItem;}
   set{_dataItem = value;}
  }
 }
}

DataBindTmp.cs
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.Collections;

namespace Hdkj.Ying
{
 [
 DefaultProperty("DataSource"),
 ParseChildren(true)
 ]
 public class DataBindTmp : System.Web.UI.WebControls.WebControl,INamingContainer
 {
  #region 定义变量
  private object _dataSource;
  private ITemplate _itemTemplate;
  private ITemplate _headerTemplate;
  
  #endregion

  #region 定义属性
  #region 属性ItemTemplate
  [
  Browsable(true),
  DefaultValue(null),
  PersistenceMode(PersistenceMode.InnerProperty),
  TemplateContainer(typeof(ItemTmp))
  ]
  public virtual ITemplate ItemTemplate
  {
   get
   {
    return _itemTemplate;
   }
   set
   {
    _itemTemplate = value;
   }
  }
  #endregion

  #region 属性HeaderTemplate
  [
  Browsable(true),
  DefaultValue(null),
  PersistenceMode(PersistenceMode.InnerProperty),
  TemplateContainer(typeof(ItemTmp))
  ]
  public virtual ITemplate HeaderTemplate
  {
   get
   {
    return _headerTemplate;
   }
   set
   {
    _headerTemplate = value;
   }
  }
  #endregion

  #region 属性DataSource
  [
  Bindable(true),
  Description("获取或者设置数据源"),
  Category("Data"),
  DefaultValue(null),
  DesignerSerializationVisibility(DesignerSerializationVisibility.Content)
  ]
  public virtual object DataSource
  {
   get
   {
    return _dataSource;
   }
   set
   {
    if(value == null || value is IEnumerable || value is IListSource)
    {
     _dataSource = value;
    }
    else
    {
     throw new ArgumentException();
    }
   }
  }
  #endregion

  #region 属性DataMember
  [
  Category("Data"),
  DefaultValue(""),
  Description("获取或者设置绑定的数据成员.")
  ]
  public virtual string DataMember
  {
   get
   {
    string s = (string)ViewState["DataMember"];
    return (s == null) ? string.Empty:s;
   }
   set
   {
    ViewState["DataMember"] = value;
   }
  } 
  #endregion
  #endregion

  #region 实现控件呈现
  //重写CreateChildControls
  protected override void CreateChildControls()
  {  
   Controls.Clear();
   if ((ViewState["ItemCount"]) != null)
   {
    CreateControlHierarchy(false);
   }
  }

  //使用数据源或者ViewState创建控件层次结构
  protected virtual void CreateControlHierarchy(bool useDataSource)
  {
   IEnumerable dataSource = null;
   int itemCount = 0;  

   if (useDataSource)
   {
    dataSource = GetDataSource();
   }
   else
   {
    dataSource = new object[(int)ViewState["ItemCount"]];
   }

   if (dataSource != null)
   {
    Table table = new Table();
    table.Attributes.Add("cellpadding","0");
    table.Attributes.Add("cellspacing","0");   
    Controls.Add(table);

    ItemTmp headerItem = new ItemTmp(null);
    if(_headerTemplate != null)
    {
     TableRow headerRow = new TableRow();
     table.Rows.Add(headerRow);
    
     ITemplate template = _headerTemplate;
     if(template != null)
     {
      template.InstantiateIn(headerItem);
     }
     headerRow.Cells.Add(headerItem);
    }
   
    IEnumerator dataItems = dataSource.GetEnumerator();
   
    while(dataItems.MoveNext())
    {
     TableRow itemRow = new TableRow();
     table.Rows.Add(itemRow);

     ItemTmp item = new ItemTmp(dataItems.Current);    
     
     ITemplate template = _itemTemplate;
     if(template != null)
     {      
      _itemTemplate.InstantiateIn(item);
     }     
     itemRow.Cells.Add(item);
     if(useDataSource)
     {
      item.DataBind();
     }
     itemCount++;
    }
   }

   if (useDataSource)
   {
    ViewState["itemCount"] = itemCount;   
   }
  }
  #endregion

  #region 实现数据绑定及相关
  public override void DataBind()
  {
   base.OnDataBinding(EventArgs.Empty);
   Controls.Clear();
   ClearChildViewState();
   TrackViewState();
   CreateControlHierarchy(true);
   ChildControlsCreated = true;
  }
 
  //获取数据源,将数据源中的数据都转换为IEnumerable类型
  protected virtual IEnumerable GetDataSource()
  {
   if (_dataSource == null)
   {
    return null;
   }           
   IEnumerable resolvedDataSource = _dataSource as IEnumerable;
   if (resolvedDataSource != null)
   {
    return resolvedDataSource;
   }
   IListSource listSource = _dataSource as IListSource;
   if (listSource != null)
   {
    IList memberList = listSource.GetList();

    if (listSource.ContainsListCollection == false)
    {
     return (IEnumerable)memberList;
    }
    ITypedList typedMemberList = memberList as ITypedList;
    if (typedMemberList != null)
    {
     PropertyDescriptorCollection propDescs = typedMemberList.GetItemProperties(new PropertyDescriptor[0]);
     PropertyDescriptor memberProperty = null;
                   
     if ((propDescs != null) && (propDescs.Count != 0))
     {
      string dataMember = DataMember;

      if (dataMember.Length == 0)
      {
       memberProperty = propDescs[0];
      }
      else
      {
       memberProperty = propDescs.Find(dataMember, true);
      }

      if (memberProperty != null)
      {
       object listRow = memberList[0];
       object list = memberProperty.GetValue(listRow);

       if (list is IEnumerable)
       {
        return (IEnumerable)list;
       }
      }
      throw new Exception("未能找到有效的DataMember.");
     }

     throw new Exception("数据源中不包含任何数据对象.");
    }
   }
   return null;
  }       
 
  private PropertyDescriptor[] GetColumnPropertyDescriptors(object dataItem)
  {
   ArrayList props = new ArrayList();
   PropertyDescriptorCollection propDescs = TypeDescriptor.GetProperties(dataItem);
   foreach (PropertyDescriptor pd in propDescs)
   {
    Type propType = pd.PropertyType;
    TypeConverter converter = TypeDescriptor.GetConverter(propType);
    if ((converter != null) && converter.CanConvertTo(typeof(string)))
    {
     props.Add(pd);
    }
   }
   props.Sort(new PropertyDescriptorComparer());
   PropertyDescriptor[] columns = new PropertyDescriptor[props.Count];
   props.CopyTo(columns, 0);
   return columns;
  }
       
  private sealed class PropertyDescriptorComparer : IComparer
  {
   public int Compare(object x, object y)
   {
    PropertyDescriptor p1 = (PropertyDescriptor)x;
    PropertyDescriptor p2 = (PropertyDescriptor)y;
    return String.Compare(p1.Name, p2.Name);
   }
  }
  #endregion
 }
}

典型应用代码如下:
private void Page_Load(object sender, System.EventArgs e)
  {
   // 在此处放置用户代码以初始化页面
   OleDbConnection oleConn = new OleDbConnection(Application["Data"].ToString());
   OleDbDataAdapter oleApt = new OleDbDataAdapter("select *from htgk",oleConn);
   DataSet dsTmp = new DataSet();
   oleApt.Fill(dsTmp,"htgk");
   DataView dvTmp = dsTmp.Tables[0].DefaultView;

   DataBindTmp2.DataSource = dvTmp;
   DataBindTmp2.DataBind();
  }

 

通过上述即实现了一个比较简单的模板化数据绑定控件,一个比较有实用价值的应用是展示图书信息的应用。具体的代码编制还需要根据实际应用的需要进行调整。

posted @ 2008-02-20 22:09  xin478  阅读(445)  评论(1编辑  收藏  举报