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

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

 

你可能感兴趣的:(checkbox)