数据对比控件
最近公司有项目需要实现一个类似pconline.com.cn的商品对比功能。相信很多在pconline.com.cn上面查过价格的人,都会使用过该功能。下面是它的效果图:
它其实是列展示每一个商品,以行展现每个商品的属性。以我们平时使用的DataGrid正好相反。为了方便和通用的实现这个功能,使用自定义控件来实现。
1、定义每行对对象GridRow
还是以pconline.com.cn的图效为例子,这个单独的一行数据:
它主要由三部分组成:
A:“显示所有参数”:这个并不是对象的属性,可用于标识每一个的属性内容
B:图片部分:这个是每个对象的属性显示部分,多个对象会产生多个列
C:行结束部分:
根据这三个属性,就可得出GridRow的主要属性了:
public class GridRow
{
///
/// 行起始
///
[TemplateContainer(typeof(TemplateItem))]
[PersistenceMode(PersistenceMode.InnerProperty)]
public ITemplate Start { get; set; }
///
/// 循环属性节点
///
[TemplateContainer(typeof(TemplateItem))]
[PersistenceMode(PersistenceMode.InnerProperty)]
public ITemplate Body { get; set; }
///
/// 行结束
///
[TemplateContainer(typeof(TemplateItem))]
[PersistenceMode(PersistenceMode.InnerProperty)]
public ITemplate End { get; set; }
}
接下来,实现以行为主的数据表格功能。
对于控件基本类的选择,以最方便实现功能为主,在这里使用CompositeDataBoundControl。CompositeDataBoundControl为我们提供了基本的表格数据绑定功能,只需要简单的对它进行扩展,即可实现丰富的自定义功能。
以以列为主的表格控件不同,这里只能定义每一行的数据,因此我们需要定义一个GridRow的集合:
///
/// 数据行
///
[PersistenceMode(PersistenceMode.InnerProperty)]
public GridRowCollection Rows { get; set; }
其中GridRowCollection是一个继承自System.Collections.CollectionBase的GridRow的强类型集合类,会在后面的详细代码中给出。
跟着实现数据绑定的功能,在这里重写CreateChildControls即可,下面是它的逻辑:
protected override int CreateChildControls(IEnumerable dataSource, bool dataBinding)
{
int index = 0;
if (dataBinding && dataSource != null && Rows != null)
{
TemplateItem ti = null;
foreach (GridRow row in Rows)
{
if (row.Start != null)
{
ti = new TemplateItem(null, index);
row.Start.InstantiateIn(ti);
Controls.Add(ti);
ti.DataBind();
}
foreach (object obj in dataSource)
{
ti = new TemplateItem(obj, index);
row.Body.InstantiateIn(ti);
Controls.Add(ti);
ti.DataBind();
}
if (row.End != null)
{
ti = new TemplateItem(null, index);
row.End.InstantiateIn(ti);
Controls.Add(ti);
ti.DataBind();
}
index++;
}
}
return index;
}
逻辑也很简单主要就是为每一行绑定它的Start、Body和End模板,并且Body模板绑定的个数来取决于控件的数据源。
至此控件的基本功能就实现了。下面是使用该控件实现数据对比功能:
Name
Name
Sex
Sex
在这里,每一个就是每一个对比的属性,后台数据绑定的方法与普通控件一致:
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Item[] items = new Item[] {
new Item("Name1", "Sex1"),
new Item("Name2", "Sex2"),
new Item("Name3", "Sex3"),
new Item("Name4", "Sex4"),
new Item("Name5", "Sex5")
};
RowDataGrid1.DataSource = items;
RowDataGrid1.DataBind();
}
}
public class Item
{
private string _name;
public string Name { get { return _name; } set { _name = value; } }
private string _sex;
public string Sex { get { return _sex; } set { _sex = value; } }
public Item(string name, string sex)
{
Name = name;
Sex = sex;
}
}
运行的效果图如下:
至此控件基本就介绍完成了,它的使用非常方便,当然功能也非常简单,可以对它进行扩展,加上相关事件让它的功能更强大。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace Guaik.WebControls
{
///
/// 以行为主的表格
///
public class RowDataGrid : CompositeDataBoundControl
{
public override void RenderBeginTag(HtmlTextWriter writer)
{
}
public override void RenderEndTag(HtmlTextWriter writer)
{
}
///
/// 数据行
///
[PersistenceMode(PersistenceMode.InnerProperty)]
public GridRowCollection Rows { get; set; }
protected override int CreateChildControls(IEnumerable dataSource, bool dataBinding)
{
int index = 0;
if (dataBinding && dataSource != null && Rows != null)
{
TemplateItem ti = null;
foreach (GridRow row in Rows)
{
if (row.Start != null)
{
ti = new TemplateItem(null, index);
row.Start.InstantiateIn(ti);
Controls.Add(ti);
ti.DataBind();
}
foreach (object obj in dataSource)
{
ti = new TemplateItem(obj, index);
row.Body.InstantiateIn(ti);
Controls.Add(ti);
ti.DataBind();
}
if (row.End != null)
{
ti = new TemplateItem(null, index);
row.End.InstantiateIn(ti);
Controls.Add(ti);
ti.DataBind();
}
index++;
}
}
return index;
}
}
public class GridRow
{
///
/// 行起始
///
[TemplateContainer(typeof(TemplateItem))]
[PersistenceMode(PersistenceMode.InnerProperty)]
public ITemplate Start { get; set; }
///
/// 循环属性节点
///
[TemplateContainer(typeof(TemplateItem))]
[PersistenceMode(PersistenceMode.InnerProperty)]
public ITemplate Body { get; set; }
///
/// 行结束
///
[TemplateContainer(typeof(TemplateItem))]
[PersistenceMode(PersistenceMode.InnerProperty)]
public ITemplate End { get; set; }
}
public class GridRowCollection : CollectionBase
{
public GridRowCollection()
{
}
public GridRow this[int index]
{
get
{
return ((GridRow)List[index]);
}
set
{
List[index] = value;
}
}
public int Add(GridRow value)
{
return (List.Add(value));
}
public int Add(GridRowCollection values)
{
int i = 0;
foreach (GridRow GridRow in values)
{
i += List.Add(GridRow);
}
return i;
}
public int IndexOf(GridRow value)
{
return (List.IndexOf(value));
}
public void Insert(int index, GridRow value)
{
List.Insert(index, value);
}
public void Remove(GridRow value)
{
List.Remove(value);
}
public bool Contains(GridRow value)
{
// If value is not of type GridRow, this will return false.
return (List.Contains(value));
}
protected override void OnInsert(int index, Object value)
{
// Insert additional code to be run only when inserting values.
}
protected override void OnRemove(int index, Object value)
{
// Insert additional code to be run only when removing values.
}
protected override void OnSet(int index, Object oldValue, Object newValue)
{
// Insert additional code to be run only when setting values.
}
protected override void OnValidate(Object value)
{
if (!(value is GridRow))
throw new ArgumentException("value must be of type GridRow.", "value");
}
}
public class TemplateItem : Control, IDataItemContainer
{
public TemplateItem()
{ }
public TemplateItem(object dataItem, int index)
{
_dataItem = dataItem;
_index = index;
}
#region IDataItemContainer 成员
object _dataItem;
public object DataItem
{
get { return _dataItem; }
}
int _index;
public int DataItemIndex
{
get { return _index; }
}
public int DisplayIndex
{
get { return _index; }
}
#endregion
public int ItemIndex
{
get { return _index; }
}
}
}
- 1. 数据对比控件2009-11-24
- 2. 页面事件顺序2009-05-07
- 3. 无限级Select联动(图)2008-09-06
- 4. 无刷新SELECT联动(图)2008-06-15





