开发模板化数据绑定控件
对于数据绑定控件的开发,其主要的要点如下:
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();
}
通过上述即实现了一个比较简单的模板化数据绑定控件,一个比较有实用价值的应用是展示图书信息的应用。具体的代码编制还需要根据实际应用的需要进行调整。