数据对比控件

最近公司有项目需要实现一个类似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; }
        }
    }
}

Tag标签: 控件 ASP.NET
发表于 2009-11-24 16:45:58 收藏 所属分类: Asp.net 网摘收藏
相关文章: