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

使用 .NET C# 的 ASP.NET 多选下拉列表

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.57/5 (5投票s)

2019年3月17日

CPOL

3分钟阅读

viewsIcon

66433

downloadIcon

859

使用 C# 和 ASP.NET 的 ASP.NET 多选下拉列表

引言

在 .NET 中,没有满足在下拉列表中选择多个项目的用户控件或自定义控件。只有 ListBox 可以完成这项工作,但它会占用大量的垂直空间,导致网页上的控件无法正确排列。此外,它还占用宝贵的页面空间。控件的正确对齐被破坏。下拉列表简洁且纤薄。有几种解决方案使用了 CheckBox,但这超出了考虑范围,您应该理解。下拉列表应该有流畅的文本,而不是其他东西。
一些解决方案使用 JavaScript(或 jQuery、AJAX、Node JS 等),但存在一些问题。

因此,仅使用 C# 和 ASP.NET 控件的解决方案至关重要。

背景

我的客户需要多选下拉列表来显示可能在手持设备(例如电子票务机 (ETM))上发现的多个缺陷或问题。我搜索了整个网络,找不到满足要求的用户控件或自定义控件。有几种解决方案使用了 CheckBox,但这超出了考虑范围。所以我决定自己编写。

Using the Code

步骤

  1. 添加新项目并选择 Web Forms ==> Web Forms 用户控件
  2. 输入名称并按“添加”按钮。

以下是 HTML 标记,其中使用了三个控件:ListBoxLinkButtonImageButton

<%@ Control Language="C#" AutoEventWireup="true" 
    CodeBehind="MultiSelectDropDown.ascx.cs" Inherits="WizDevice.MultiSelectDropDown" %>
<html id="t" runat="server">
    <head>
        <title>Multiselect DorpDownList</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta name="author" content="Nitin Rajurkar" />
        <meta content="False" name="vs_snapToGrid" />
        <meta content="True" name="vs_showGrid" />
        <style>
            .CursorStyle {
                cursor:default;
            }
            .LinkStyle {
                cursor:default;
                color: #000000; 
                text-decoration: none;
            }
            .LinkStyle:hover {
                text-decoration: none;
            }
        </style>
    </head>
    <body>
        <asp:Panel ID="MultiSelect_Panel" runat="server" 
        Height="1px" Width="252px" BackColor="White">
            <table id="MultiSelect_Table" runat="server" style="table-layout:fixed; 
             height:16px; border-color:#cccccc; width:100%; border:groove;">
                <tr id="MultiSelect_TableRow" style="height:12px;" runat="server">
                    <td>
                        <asp:LinkButton ID="MultiSelect_LinkButton" runat="server" 
                         CssClass="LinkStyle" Width="252px" Font-Size="Small" 
                         Font-Names="Arial" BorderColor="Transparent" BorderStyle="None" 
                            Height="12px" ToolTip="" OnClick="MultiSelect_LinkButton_Click">
                        </asp:LinkButton>
                    </td>
                    <td id="MultiSelect_Image" style="padding-right: 0px; padding-left: 0px; 
                     padding-bottom: 0px; padding-top: 0px; width: 16px;" runat="server">
                        <asp:ImageButton ID="MultiSelect_ImageButton" runat="server" 
                         ImageUrl="~/Resources/DropDown.bmp" CssClass="CursorStyle" 
                         OnClick="MultiSelect_ImageButton_Click" />
                    </td>
                </tr>
            </table>
            <div id="MultiSelect_div" style="z-index:9999; position:absolute">
                <asp:ListBox ID="MultiSelect_ListBox" runat="server" 
                 Width="100%" SelectionMode="Multiple"
                    OnSelectedIndexChanged="MultiSelect_ListBox_SelectedIndexChanged" >
              </asp:ListBox>
            </div>
        </asp:Panel>
    </body>
</html>

在这里,您可以使用 Label 代替 LinkButton,但 Label 没有点击事件,但如果您愿意,可以添加它。需要样式才能使 LinkButton 显示为普通的 Label。为每个控件提供 id 以避免出现错误“Error Rendering Control. An unhandled exception has occurred.

在代码隐藏中,提供了 public 属性,用于在网页中使用该控件,例如,更改 WidthHeight,设置显示文本,设置和获取选定的文本、值和项目。使用的控件 ListBoxLinkButton 也可供用户使用。您可以创建自定义事件。提供了 LostFocus (blur) 事件,以便如果下拉列表已打开(高度 > 0),则它会在失去焦点后立即关闭。这是正确的行为。

protected void Page_Init(object sender, EventArgs e)
        {
            var OnLostFocus = Page.ClientScript.GetPostBackEventReference
                                   (MultiSelect_ListBox, "OnBlur");
            MultiSelect_ListBox.Attributes.Add("onblur", OnLostFocus);
        }
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                MultiSelect_ListBox.Height = 0;
                if (MultiSelect_ListBox.Items.Count > 0)
                {
                    MultiSelect_LinkButton.Text = ItemText.Text;
                }
                else
                {
                    MultiSelect_LinkButton.Text = string.Empty;
                }
            }
            else
            {
                MultiSelect_LinkButton.Text = SelectedText;
                MultiSelect_LinkButton.ToolTip = SelectedText;
                var ControlObject = Request.Params[Page.postEventSourceID];
                var ControlFeature = Request.Params[Page.postEventArgumentID];
                OnLostFocus(ControlObject, ControlFeature);
            }
        }
         private void OnLostFocus(string ControlName, string ControlProperty)
        {
            if ((ControlName == MultiSelect_ListBox.UniqueID) && (ControlProperty == "OnBlur"))
            {
                MultiSelect_ListBox.Height = 0;
            }
        }

多选的各种属性

以下是使用 Multiselect Dropdownlist 控件所需的 public 属性

    #region  Public properties
        private string _SelectedItem;
        public double ListWidth 
        { 
           get 
           { 
              return MultiSelect_Panel.Width.Value; 
           } 
           set 
           { 
              MultiSelect_Panel.Width = (Unit)value; 
           } 
        }        
public ArrayList SelectedValues 
{ 
    get 
    { 
        ArrayList selectedValues = new ArrayList(); 
        foreach (ListItem li in MultiSelect_ListBox.Items) 
        { 
            if (li.Selected) 
            { 
                selectedValues.Add(li.Value); 
            } 
        } 
        return selectedValues; 
     } 
}
public ArrayList SelectedTexts 
{ 
    get 
    { 
        ArrayList selectedTexts = new ArrayList(); 
        foreach (ListItem li in MultiSelect_ListBox.Items) 
        { 
            if (li.Selected) 
            { 
                selectedTexts.Add(li.Text); 
            } 
        } 
        return selectedTexts; 
    } 
}
public string SelectedText 
{ 
    get 
    {
        string UserSelectedText = string.Empty; 
        foreach (ListItem li in MultiSelect_ListBox.Items) 
        { 
            if (li.Selected) 
            {  
                 UserSelectedText += li.Text + ","; 
            } 
        } 
        if (UserSelectedText.Length > 0) 
            UserSelectedText = UserSelectedText.Length > 0 ? 
            UserSelectedText.Substring(0, UserSelectedText.Length - 1) : UserSelectedText; 
            return UserSelectedText; 
    } 
    set 
    { 
        _SelectedItem = value; 
        MultiSelect_LinkButton.Text = _SelectedItem; 
        MultiSelect_LinkButton.ToolTip = _SelectedItem; 
    } 
}
public ArrayList SelectedItems 
{ 
    get 
    {
        ArrayList UserSelectedItems = new ArrayList(); 
        foreach (ListItem li in MultiSelect_ListBox.Items) 
        {
            if (li.Selected) 
            {
                UserSelectedItems.Add(li); 
            }
        }
        return UserSelectedItems; 
    } 
    set 
    { 
        ArrayList UserSelectedItems = value; 
        string SelectedElement = string.Empty;  
        foreach (ListItem li in MultiSelect_ListBox.Items) 
        {
            li.Selected = false; 
        }
        foreach (string ItemElement in UserSelectedItems) 
        {
            ListItem li = MultiSelect_ListBox.Items.FindByText(ItemElement); 
            if (li != null) 
            {
                li.Selected = true; 
                SelectedElement += li.Text + ","; 
            } 
        } 
        if (SelectedElement.Length > 0) 
            SelectedElement = SelectedElement.Length > 0 ? 
            SelectedElement.Substring(0, SelectedElement.Length - 1) : SelectedElement; 
            SelectedText = SelectedElement; 
    } 
}
public ListBox List 
{ 
    get 
    {
        return MultiSelect_ListBox; 
    }
    set
    {
        MultiSelect_ListBox = List; 
    } 
} 
public LinkButton ItemText 
{ 
    get 
    { 
        return MultiSelect_LinkButton; 
    } 
    set 
    { 
        MultiSelect_LinkButton = ItemText; 
    } 
} 
#endregion 
public void Clear() 
{ 
    MultiSelect_ListBox.Items.Clear(); 
}

事件

单击箭头或整个框会产生切换效果,即,如果关闭,则单击时会打开,反之亦然。为此,提供了点击事件。同时,还提供了 SelectedIndexChanged 事件。

    protected void MultiSelect_ImageButton_Click(object sender, System.Web.UI.ImageClickEventArgs e)
        {
            Unit List_Height = MultiSelect_ListBox.Height;
            if (List_Height.Value == 0.0)
            {
                MultiSelect_ListBox.Height = 160;
            }
            else
            {
                MultiSelect_ListBox.Height = 0;
            }
        }

        protected void MultiSelect_LinkButton_Click(object sender, EventArgs e)
        {
            Unit List_Height = MultiSelect_ListBox.Height;
            if (List_Height.Value == 0.0)
            {
                MultiSelect_ListBox.Height = 160;
            }
            else
            {
                MultiSelect_ListBox.Height = 0;
            }
        }

用法和填充

要在网页中使用它,请相应地更改 Web.Config,如下所示

<pages>
      <controls>
        <add tagPrefix="CC" src="~/MultiSelectDropDown.ascx" tagName="MultiSelect"/>
      </controls>
</pages>

您可以使用自己的 tagPrefixtagName

然后在网页中编写以下标记

    <CC:MultiSelect ID="Problems_DropDownList" runat="server"></CC:MultiSelect>

您可以通过任何方法填充它。通常,它从数据库检索的数据填充。要设置多选,可以使用 string 元素准备 ArrayList。但是,您可能有 ListItems,在这种情况下,将 foreach (string ItemElement in SelectedItems) 更改为 (ListItem ItemElement in SelectedItems),并相应地更改为 ListItem li = MultiSelect_ListBox.Items.FindByText(ItemElement.ToString()); 因为 string 无法转换为 ListItem,但反之则可以。

在此网页的代码隐藏中,填充下拉列表,如下所示

    protected void Load_DefectList()
        {
            try
            {
                SqlDataAdapter Defect_SqlDataAdapter = 
                     new SqlDataAdapter("Load_DefectList", Dal_Obj.OpenConnection());
                Defect_SqlDataAdapter.SelectCommand.CommandType = CommandType.StoredProcedure;
                Defect_SqlDataAdapter.SelectCommand.Parameters.AddWithValue
                     ("@LanguageId", Session["LanguageId"]);
                Defect_SqlDataAdapter.SelectCommand.Parameters.AddWithValue
                     ("@HostId", Session["HostId"]);

                DataSet Defect_DataSet = new DataSet();
                Defect_SqlDataAdapter.Fill(Defect_DataSet);
                if (Defect_DataSet.Tables[0].Rows.Count > 0)
                {
                    Problems_DropDownList.List.DataTextField = 
                              Defect_DataSet.Tables[0].Columns["Defect"].ToString();
                    Problems_DropDownList.List.DataValueField = 
                              Defect_DataSet.Tables[0].Columns["DefectId"].ToString();
                    Problems_DropDownList.List.DataSource = Defect_DataSet.Tables[0];
                    Problems_DropDownList.List.DataBind();
                }
            }
            catch (Exception Defect_Exception)
            {
                if (Defect_Exception.Message != null)
                {
                    Response.Write("alert('Error encountered while loading conductors. 
                                    Please contact support.')");
                }
            }
            finally
            {
                Dal_Obj.CloseConnection();
            }
        }

要显示已经分配了多个值(例如在“View”或“Modify”中),请执行以下操作

    if (DefectiveDevice_DataSet.Tables[1].Rows.Count > 0)
                {
                    ArrayList ReportedDefects = new ArrayList();
                    int TotalDefect = DefectiveDevice_DataSet.Tables[1].Rows.Count;
                    for (int i = 0; i < DefectiveDevice_DataSet.Tables[1].Rows.Count; i++)
                    {
                         ReportedDefects.Add(DefectiveDevice_DataSet.Tables[1].Rows[i]["Defect"]);
                    }
                    Problems_DropDownList.SelectedItems = ReportedDefects;
                }

通过使用表类型(在 SQL Server 中),您可以将多个值以表格形式发送到数据库,以进行 insertupdatedelete 操作。请参阅附加代码。享受使用此控件。

关注点

类型转换:string 无法转换为 ListItem,但反之则可以。

LostFocus 事件不可直接使用。我们正在使用 blur 事件。

历史

这是第一个版本。我将根据情况提供新版本。

© . All rights reserved.