多级Repeater嵌套,CheckBoxList赋值与读取

最近在做电脑维修网时,需要制作一个信息订阅选择的功能,需根据数据库中的类别进行动态的生成CheckBox,以及对其赋值和读取。

格式大致为:存在数据库中必定是按照“1,2,3,4”用逗号分隔的字符串。现在要做的核心就是根据该字符串动态的给CheckBox赋值,以及把选中的CheckBox读取为其格式。

根据类别遍历生成CheckBox,首选用到的2个服务器组件并定是Repeater以及CheckBoxList。

由于此处主要展示功能性代码,由此未对页面进行任何的美化处理,页面代码如下:

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Repeater嵌套CheckBoxList读取赋值Demo</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Repeater ID="Repeater1" runat="server" OnItemDataBound="Repeater1_ItemDataBound">
            <ItemTemplate>
                <div style="color: Red;">
                    <%# Eval("Name")%><asp:HiddenField ID="hidID" runat="server" Value='<%# Eval("Id")%>' />
                </div>
                <asp:Repeater ID="Repeater2" runat="server" OnItemDataBound="Repeater2_ItemDataBound">
                    <ItemTemplate>
                        <div style="padding: 10px 10px;">
                            <%# Container.ItemIndex+1 %><%# Eval("Name")%><br />
                            <br />
                            <asp:CheckBoxList ID="cbxName" runat="server" RepeatDirection="Horizontal" RepeatLayout="Flow">
                            </asp:CheckBoxList>
                        </div>
                    </ItemTemplate>
                </asp:Repeater>
            </ItemTemplate>
        </asp:Repeater>
        <asp:Button ID="btnSubmit" runat="server" Text="提交" OnClick="btnSubmit_Click" />
    </div>
    </form>
</body>
</html>

一共是三层嵌套,Repeater-Repeater-CheckBoxList,数据源使用数据库比较麻烦,因此作为Demo,随便虚拟一个数据源即可。如下是数据源生成代码:

/// <summary>
///Entity 的摘要说明
/// </summary>
public class Entity
{
    private int _id;
    /// <summary>
    /// 主键
    /// </summary>
    public int Id
    {
        get { return _id; }
        set { _id = value; }
    }
    private string _name;
    /// <summary>
    /// 名称
    /// </summary>
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }
    private int _parent;

    /// <summary>
    /// 父节点
    /// </summary>
    public int Parent
    {
        get { return _parent; }
        set { _parent = value; }
    }
    private bool _check;
    /// <summary>
    /// 选中状态
    /// </summary>
    public bool Check
    {
        get { return _check; }
        set { _check = value; }
    }

    private List<Entity> _list;

    /// <summary>
    /// 动态生成的集合
    /// </summary>
    public List<Entity> List
    {
        get { return _list; }
        set { _list = value; }
    }
    public Entity()
    {

    }
    /// <summary>
    /// 获取虚拟列表
    /// </summary>
    public void GetList()
    {
        List = new List<Entity>();
        int primaryKey = 1;
        for (int i = 0; i < 2; i++)
        {
            Entity obj = new Entity();
            obj.Id = primaryKey;
            obj.Name = "电脑维修网" + primaryKey;
            obj.Parent = 0;
            obj.Check = true;
            List.Add(obj);
            primaryKey++;
            for (int j = 0; j < 3; j++)
            {
                Entity obj2 = new Entity();
                obj2.Id = primaryKey;
                obj2.Name = "维修类型" + primaryKey;
                obj2.Parent = obj.Id;
                obj2.Check = true;
                List.Add(obj2);
                primaryKey++;
                for (int m = 0; m < 2; m++)
                {
                    Entity obj3 = new Entity();
                    obj3.Id = primaryKey;
                    obj3.Name = "维修项目" + primaryKey;
                    obj3.Parent = obj2.Id;
                    obj3.Check = true;
                    List.Add(obj3);
                    primaryKey++;
                }
            }
        }
    }
}

后台代码如下:

Entity entity = new Entity();
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            //获取虚拟数据集合
            entity.GetList();
            //Repeater数据绑定
            Repeater1.DataSource = entity.List.Where(o => o.Parent == 0);
            Repeater1.DataBind();
            //给CheckBoxList赋值
            SetCheckBoxValue("3,4,6,7");
        }
    }
    /// <summary>
    /// 根据后台返回的数据列,为复选框赋值
    /// </summary>
    /// <param name="follow">以逗号分割的字符串</param>
    private void SetCheckBoxValue(string followStr)
    {
        //如果字符为空,不做任何操作
        if (string.IsNullOrEmpty(followStr))
        {
            return;
        }
        string[] follow = followStr.Split(',');
        /*
         * 首先说明下层级关系
         * 第一层为Repeater,里边继续嵌套一个Repeater,然后在嵌套的Repeater中嵌套CheckBoxList
         * Repeater-Repeater-CheckBoxList
         * 理解了嵌套关系,就很容易理解应该去如何遍历
         */
        //遍历主Repeater,然后对其子Repeater进行遍历,获取到CheckBoxList进行赋值
        for (int i = 0; i < Repeater1.Items.Count; i++)
        {
            //获取子Repeater
            Repeater rep2 = ((Repeater)Repeater1.Items[i].FindControl("Repeater2"));
            //对子Repeater进行遍历,获取到CheckBoxList进行赋值
            for (int j = 0; j < rep2.Items.Count; j++)
            {
                //获取第二层Repeater的CheckBoxList
                CheckBoxList cbxThreeList = ((CheckBoxList)rep2.Items[j].FindControl("cbxName"));
                foreach (ListItem item in cbxThreeList.Items)
                {
                    foreach (string s in follow)
                    {
                        if (item.Value == s)
                        {
                            item.Selected = true;
                        }
                    }
                }
            }
        }
    }
    /// <summary>
    /// 获得前台选中值
    /// </summary>
    /// <returns>获取选中CheckBoxList的值,并用逗号分隔</returns>
    private string GetCheckBoxValue()
    {
        string follow = "";
        for (int i = 0; i < Repeater1.Items.Count; i++)
        {
            Repeater rep2 = ((Repeater)Repeater1.Items[i].FindControl("Repeater2"));
            for (int j = 0; j < rep2.Items.Count; j++)
            {
                CheckBoxList cbxThreeList = ((CheckBoxList)rep2.Items[j].FindControl("cbxName"));
                foreach (ListItem item in cbxThreeList.Items)
                {
                    if (item.Selected == true)
                    {
                        follow += item.Value + ",";
                    }
                }
            }
        }
        return follow.TrimEnd(',');
    }
    /// <summary>
    /// 第一层Repeater数据绑定时,进行第二层Repeater数据的绑定
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
    {
        // ItemDataBound事件触发的项包括页眉、页脚、分隔符和项。
        // 对类型进行筛选,只执行类型为项或者交替单元格中的项。
        if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
        {
            Repeater rep = ((Repeater)e.Item.FindControl("Repeater2"));
            //不用在前台输出隐藏标签,直接从数据源中读取数据,这样省去了前台的标签,可能有利于优化
            //Entity rowDate = e.Item.DataItem as Entity;
            //rep.DataSource = entity.List.Where(o => o.Parent == rowDate.Id);
            //在前台生成一个隐藏标签用于存值
            HiddenField hidID = ((HiddenField)e.Item.FindControl("hidID"));
            rep.DataSource = entity.List.Where(o => o.Parent == Convert.ToInt16(hidID.Value));
            rep.DataBind();
        }

    }
    /// <summary>
    /// 第二层Repeater数据绑定时,进行第三层CheckBoxList数据的绑定
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void Repeater2_ItemDataBound(object sender, RepeaterItemEventArgs e)
    {
        // This event is raised for the header, the footer, separators, and items.
        // Execute the following logic for Items and Alternating Items.
        if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
        {
            CheckBoxList cbxName = ((CheckBoxList)e.Item.FindControl("cbxName"));
            cbxName.DataTextField = "Name";
            cbxName.DataValueField = "Id";
            //不用在前台输出隐藏标签,直接从数据源中读取数据,这样省去了前台的标签,可能有利于优化
            Entity rowDate = e.Item.DataItem as Entity;
            cbxName.DataSource = entity.List.Where(o => o.Parent == rowDate.Id);
            cbxName.DataBind();
        }

    }
    /// <summary>
    /// 提交按钮执行的事件,用于显示勾选的项
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnSubmit_Click(object sender, EventArgs e)
    {
        HttpContext.Current.Response.Write("<script language='javascript'>alert('选择的项:" + GetCheckBoxValue() + "');</script>");
    }

动态生成CheckBox的核心代码都在ItemDataBound事件中,赋值和读取核心代码在方法SetCheckBoxValue与GetCheckBoxValue中。

在Repeater1_ItemDataBound事件中有2个小技巧,那就是如何得到行数据的值,这里我在需要读取ID。

有2种解决方案:

第一种使用e.Item.DataItem属性,直接从绑定到Repeater的数据源中读取该行对应的数据对象,通过把其转换为具体的对象来进行数据的读取。个人比较喜欢用该方法。代码相对而言比较简洁。

第二种直接就是在前台放一个HiddenField把ID隐藏在其中,后台通过获取该组件,然后读取该组件的值进行数据的读取,此方案使用起来比较繁琐,个人不推荐使用。

不知是否还有其他读取方案,有兴趣的朋友可以研究研究。如果你有更好的解决方案,希望不要吝啬,能拿出来探讨探讨,以便代码的优化。毕竟学习本来就是一件分享的事情。

 

posted @ 2013-06-06 16:31  [FRL]...MoNey  阅读(1188)  评论(0编辑  收藏  举报