zoukankan      html  css  js  c++  java
  • 多级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隐藏在其中,后台通过获取该组件,然后读取该组件的值进行数据的读取,此方案使用起来比较繁琐,个人不推荐使用。

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

  • 相关阅读:
    LeetCode Binary Tree Inorder Traversal
    LeetCode Populating Next Right Pointers in Each Node
    LeetCode Construct Binary Tree from Inorder and Postorder Traversal
    LeetCode Reverse Linked List II
    LeetCode Populating Next Right Pointers in Each Node II
    LeetCode Pascal's Triangle
    Palindrome Construct Binary Tree from Preorder and Inorder Traversal
    Pascal's Triangle II
    LeetCode Word Ladder
    LeetCode Binary Tree Zigzag Level Order Traversal
  • 原文地址:https://www.cnblogs.com/frlmoney/p/3121473.html
Copyright © 2011-2022 走看看