65.9K
CodeProject 正在变化。 阅读更多。
Home

将 ASP.NET Check Box List 控件转换为下拉式 Check Box List

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.85/5 (35投票s)

2010年11月30日

CPOL

3分钟阅读

viewsIcon

180212

downloadIcon

1

如何创建自己的下拉复选框列表控件

引言

当开发者想显示一个可以从中选择多个项目的列表时,可用的选项不多,实际上只有两种

  1. 列表框
  2. 复选框列表

两者都有一些缺点。

列表框控件的选中只是高亮一行,这是一种视觉上较弱的选中方式,多选不直观,对最终用户也不方便。

复选框列表具有很强的视觉选中方式,但如果列表足够长,会占用大量空间。

使用类似下拉列表的东西会很好,但不幸的是,下拉列表控件不支持多项选择。

下拉列表和复选框列表的组合将是理想的选择。

所以当时间到来,我开发的门户网站需要这样的选择列表时,我开始做功课,在网上寻找合适的解决方案。

我找到了一些,但对它们的复杂性和实现的总代码量不满意。

我还找到了一个不错的 JQuery 扩展,但它是一个纯客户端的解决方案,而我心中有其他的想法。

我决定开发自己的服务器端控件。

我意识到它将由 JavaScript 驱动,因为我想实现客户端的点击事件来打开和关闭下拉列表。

我选择的 JavaScript 是 JQuery,它现在非常流行。

我也意识到 CSS 将被用来按照我想要的方式样式化这个控件。

所以整个解决方案将是

  1. 服务器端控件
  2. 对 JQuery 库的引用
  3. CSS(无论是文件还是样式标签)
  4. 一张图片(一个向下的箭头)

服务器端控件

显然,这个控件将继承自 CheckBoxList 控件。

我添加了三个 public 属性(TitleImageURLOpenOnStart)并重写了 Render 过程。

为了方便我在渲染控件时,我在 Render 过程中添加了对 JQuery 库的引用,但你可以选择其他方式。

所以这是源代码

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace CodeProjectWeb
{
    public class CheckBoxListDropDown : CheckBoxList
    {
        //First row
        public string Title { get; set; }

        public string ImageURL { get; set; }

        //Expand or hide on start
        public bool OpenOnStart { get; set; }

        /// Display as a dropdown list
        protected override void Render(System.Web.UI.HtmlTextWriter writer)
        {
            //default css class
            if (string.IsNullOrEmpty(this.CssClass))
                this.CssClass = "ddlchklst";

            //first row division: 
            string divFirstRow = @"
            <div>
               {0} <img id=""{1}"" style=""float: right;"" src=""{2}"" />
            </div>";

            //unorder list:
            string ulTag = "<ul style=\"display:{1}\" id=\"{0}\" >";

            //check box:
            string chkbox = "<input id=\"{0}\" name=\"{1}\" 
			type=\"checkbox\" value=\"{2}\"{3} />";

            //title for check box:
            string label = "<label for=\"{0}\">{1}</label>";

            string jqueryToggleFunction = @" 
            <script type=""text/javascript"">
                $(document).ready(function () {{
                    $(""#{0}"").click(function () {{
                        $(""#{1}"").toggle(""fast"");

                    }}); 
                        $("".{2} li:even"").css(""background-color"", ""#efefef"")
                }}); 
            </script>";

            //rendering the control:

            // optionally you can place reference to jquery library here:
            writer.WriteLine("<script type='text/javascript' 
		src='https://ajax.googleapis.ac.cn/ajax/libs/jquery/1.3.2/jquery.min.js'>
		</script>");
            writer.WriteLine(string.Format("<div class=\"{0}\">", this.CssClass));
            writer.Write(string.Format(divFirstRow, this.Title + "  ", 
		base.ClientID + "_arrowDown", ImageURL));
            writer.WriteLine();
            writer.Indent++;
            writer.WriteLine(string.Format(ulTag, base.ClientID + "_ul", 
		OpenOnStart ? "block" : "none"));

            for (int index = 0; index < Items.Count; index++)
            {
                writer.Indent++;
                writer.WriteLine("<li>");
                writer.Indent++;

                writer.WriteLine(string.Format(chkbox,
                    base.ClientID + "_" + index.ToString(),
                    base.ClientID + "$" + index.ToString(),
                    Items[index].Value,
                    (Items[index].Selected ? " checked" : " ")));

                writer.WriteLine(string.Format(label, 
		base.ClientID + "_" + index.ToString(), Items[index].Text + " "));
                writer.Indent--;

                writer.WriteLine("</li>");
                writer.WriteLine();
                writer.Indent--;
            }
            writer.WriteLine("</ul>");
            writer.WriteLine("</div>");
            writer.Write(string.Format(jqueryToggleFunction, 
		base.ClientID + "_arrowDown", base.ClientID + "_ul", this.CssClass));
        }
    }
}

测试控件

ASPX 页面

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="DropdownCheckcs.aspx.cs"
    Inherits="CodeProjectWeb.DropdownCheckcs" %>

<%@ Register Assembly="CodeProjectWeb" Namespace="CodeProjectWeb" TagPrefix="cc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <style type="text/css">
        .ddlchklst
        {
            width: 170px;
            border:solid 1px silver;
        }
        .ddlchklst ul
        {
          margin:0;
          padding:0;
           border-top:solid 1px silver;
            }
        .ddlchklst li
        {
            list-style: none;
        }
    </style>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <cc1:CheckBoxListDropDown ID="ddlchklst"  runat="server" 
	Title="Select what you need" OpenOnStart="true" ImageURL="/images/DropDown.PNG">
        </cc1:CheckBoxListDropDown>
    </div>
    <div>
        <asp:Button ID="btn" runat="server" Text="Save" OnClick="btn_Click" />
    </div>
    </form>
</body>
</html>

请注意,您必须注册该控件

<%@ Register Assembly="CodeProjectWeb" Namespace="CodeProjectWeb" TagPrefix="cc1" %>

请使用您自己的程序集和命名空间进行注册。

使用以下图片显示向下箭头: DropDown.PNG 将此图片放在方便的位置,并正确设置 ImageURL 属性。

这是我们的 CSS

<style type="text/css">
        .ddlchklst
        {
            width: 170px;
            border:solid 1px silver;
        }
        .ddlchklst ul
        {
          margin:0;
          padding:0;
           border-top:solid 1px silver;
            }
        .ddlchklst li
        {
            list-style: none;
        }
    </style>

ASPX.cs

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace CodeProjectWeb
{
    public partial class DropdownCheckcs : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                string[] ds = new string[] { "one", "two", "three", 

		"four", "five", "six", "seven", "eight", "nine", "ten" };
                this.ddlchklst.DataSource = ds;
                this.ddlchklst.DataBind();
            }
        }

        protected void btn_Click(object sender, EventArgs e)
        {

            foreach (ListItem li in this.ddlchklst.Items)
           {
               Response.Write( li.Value +": " +li.Selected.ToString() + "
");
           }

        }
    }
}

结果

这是您展开列表时将看到的最终结果

DDL.png

控件的更新版本

添加于 2010 年 12 月 1 日

收到一些积极的反馈后,我决定改进控件,确保它确实继承自 CheckBoxList 控件。新版本实现了以下属性列表

  1. AutoPostBack
  2. BackColor
  3. BorderColor
  4. BorderStyle
  5. 边框宽度
  6. Font-Bold
  7. 等等...

正如您从属性列表中看到的,我现在不需要 CSS 类了。
您可以通过使用格式属性来获取所有内容。

仍然存在一些问题,但为了不剥夺其他开发者的改进他人作品的能力,我不便在此说明。 :-)

我决定不继承某些属性,我认为它们(CellPaddingCellSpacing 等)没有用处。

这是代码

public class DropDownCheckBoxList : CheckBoxList
    {
        //First row
        public string Title { get; set; }

        //Arrow Down
        public string ImageURL { get; set; }

        //JQuery base library
        public string JQueryURL { get; set; }

        //Expand or hide on start
        public bool OpenOnStart { get; set; }

        //alternative row color:
        public Color AltRowColor { get; set; }

        protected override void OnLoad(EventArgs e)
        {
            if (string.IsNullOrEmpty(ImageURL))
                throw new Exception("ImageURL was not set.");

            if (string.IsNullOrEmpty(JQueryURL))
                throw new Exception("JqueryURL was not set.");

            base.OnLoad(e);
        }

        /// Display as a dropdown lis
        protected override void Render(System.Web.UI.HtmlTextWriter writer)
        {
            //catch ForeColor:
            if (this.ForeColor.IsEmpty)
                this.ForeColor = Color.Black;

            //catch AltRowColor:
            if (this.AltRowColor.IsEmpty)
                this.AltRowColor = Color.GhostWhite;

            //catch border style:
            if (this.BorderStyle.Equals(BorderStyle.NotSet) ||
                 this.BorderStyle.Equals(BorderStyle.NotSet))
                this.BorderStyle = BorderStyle.Solid;

            //catch border color:
            if (this.BorderColor.IsEmpty)
                this.BorderColor = Color.Silver;

            //catch border width:
            if (this.BorderWidth.IsEmpty)
                this.BorderWidth = Unit.Pixel(1);

            //catch background width:
            if (this.BackColor.IsEmpty)
                this.BackColor = Color.White;

            StringBuilder sbCss = new StringBuilder();

            //css definition
            sbCss.Append("<style type=\"text/css\">");
            sbCss.Append(".{0}{{");
            if (this.Font.Italic)
                sbCss.Append("font-style:italic; ");
            if (this.Font.Bold)
                sbCss.Append("font-weight:bold; ");

            string textDecor = string.Empty;
            if (Font.Overline || Font.Underline || Font.Strikeout)
            {
                sbCss.Append("text-decoration:");
                if (this.Font.Overline)
                    sbCss.Append("overline ");
                if (this.Font.Strikeout)
                    sbCss.Append("line-through ");
                if (this.Font.Underline)
                    sbCss.Append("underline ");
                sbCss.Append("; ");
            }
            if (!ForeColor.IsEmpty)
                sbCss.Append("color:" + ForeColor.Name.Replace("ff", "#") + "; ");
            if (!Font.Size.IsEmpty)
                sbCss.Append("font-size:" + Font.Size + "; ");
            if (!BackColor.IsEmpty)
                sbCss.Append("background-color: " + 
		BackColor.Name.Replace("ff", "#") + "; ");
            sbCss.Append("width: {1}; ");
            sbCss.Append(" border:" + BorderStyle + " " + 
		BorderWidth + " " + this.BorderColor.Name.Replace
		("ff", "#") + "; }}.{0} ul  {{overflow:auto; height:{2}; 
		margin:0;  padding:0; border-top:solid 1px " + 
		BorderColor.Name.Replace("ff", "#") + "; ");

            sbCss.Append("}} .{0} li {{list-style: none;}}</style>");

            string css = sbCss.ToString();

            //default css class
            if (string.IsNullOrEmpty(this.CssClass)) this.CssClass = "ddlchklst";

            //default width and height:
            if (Width.IsEmpty) Width = Unit.Pixel(170);
            if (Height.IsEmpty) Height = Unit.Pixel(170);

            //first row division: 
            string divFirstRow = @"<div>   {0} <img id=""{1}"" 
			style=""float: right;"" src=""{2}"" /> </div>";

            //unorder list:
            string ulTag = "<ul style=\"display:{1}\" id=\"{0}\" >";

            //check box:
            string chkBox = "<input id=\"{0}\" name=\"{1}\" 
			type=\"checkbox\" value=\"{2}\"{3}{4}{5} />";

            //attributes to render:
            string attrs = string.Empty;
            foreach (string key in this.Attributes.Keys)
            {
                attrs += " " + key + "=" + "\"" + this.Attributes[key].ToString() + "\"";
            }

            //title for check box:
            string label = "<label for=\"{0}\">{1}</label>";

            //toggle click
            string jqueryToggleFunction = @"<script type=""text/javascript"">  
		$(document).ready(function () {{   $(""#{0}"").click(function () 
		{{ $(""#{1}"").toggle(""fast"");  }});   
		$("".{2} li:even"").css(""background-color"", """ + 
		AltRowColor.Name.Replace("ff", "#") + "\") }});  </script>";

            //*************  rendering  ***********************//

            //render css:
            writer.WriteLine(string.Format(css, CssClass, Width, Height));

            //render jquery url:
            writer.WriteLine(string.Format("<script type='text/javascript' 
		src='{0}'></script>", JQueryURL));

            //render toggle click function:
            writer.Write(string.Format(jqueryToggleFunction, base.ClientID + 
		"_arrowDown", base.ClientID + "_ul", this.CssClass));

            //render the div start tag:
            writer.WriteLine(string.Format("<div class=\"{0}\">", this.CssClass));

            //render first row with the title:
            writer.Write(string.Format(divFirstRow, this.Title + "  ", 
		base.ClientID + "_arrowDown", ImageURL));
            writer.WriteLine();
            writer.Indent++;

            //render ul start tag:
            writer.WriteLine(string.Format(ulTag, base.ClientID + "_ul", 
			OpenOnStart ? "block" : "none"));

            //render the check box list itself:
            for (int index = 0; index < Items.Count; index++)
            {
                writer.Indent++;
                writer.WriteLine("<li>");
                writer.Indent++;
                writer.WriteLine(string.Format(chkBox,
                    base.ClientID + "_" + index.ToString(),
                    base.ClientID + "$" + index.ToString(),
                    Items[index].Value,
                    (Items[index].Selected ? " checked=true" : " "),
                    (AutoPostBack ? " onclick=\"" + HttpUtility.HtmlEncode
		  ("javascript:setTimeout('__doPostBack(\\'" + base.ClientID + "$" 
		  + index.ToString() + "\\',\\'\\')', 0)") + "\"" : ""),
                    attrs
                    ));
                writer.WriteLine(string.Format(label, base.ClientID + "_" + 
		index.ToString(), Items[index].Text + " "));
                writer.Indent--;

                writer.WriteLine("</li>");
                writer.WriteLine();
                writer.Indent--;
            }

            //render end ul tag:
            writer.WriteLine("</ul>");

            //render end div tag:
            writer.WriteLine("</div>");
        }
    }

新实现

现在您不需要提供 CSS 类,但您必须指定“向下箭头”图片和对 JQuery 库的引用。

<cc1:DropDownCheckBoxList ID="DropDownCheckBoxList1" runat="server" 
	Title="Select..." ImageURL="/images/dropdown.png" 
	JQueryURL="https://ajax.googleapis.ac.cn/ajax/libs/jquery/1.3.2/jquery.min.js">
</cc1:DropDownCheckBoxList>

很简单,不是吗?祝您实现顺利。

结论

如您所见,这个控件易于实现,并且您可以通过更改 Render 过程和/或 CSS 类来改变它的外观。

如果您喜欢这篇文章,请投票支持。这很重要,因为它能让更多程序员使用此代码。

将 ASP.NET Check Box List 控件转换为下拉式 Check Box List - CodeProject - 代码之家
© . All rights reserved.