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






4.57/5 (5投票s)
使用 C# 和 ASP.NET 的 ASP.NET 多选下拉列表
引言
在 .NET 中,没有满足在下拉列表中选择多个项目的用户控件或自定义控件。只有 ListBox
可以完成这项工作,但它会占用大量的垂直空间,导致网页上的控件无法正确排列。此外,它还占用宝贵的页面空间。控件的正确对齐被破坏。下拉列表简洁且纤薄。有几种解决方案使用了 CheckBox
,但这超出了考虑范围,您应该理解。下拉列表应该有流畅的文本,而不是其他东西。
一些解决方案使用 JavaScript(或 jQuery、AJAX、Node JS 等),但存在一些问题。
因此,仅使用 C# 和 ASP.NET 控件的解决方案至关重要。
背景
我的客户需要多选下拉列表来显示可能在手持设备(例如电子票务机 (ETM))上发现的多个缺陷或问题。我搜索了整个网络,找不到满足要求的用户控件或自定义控件。有几种解决方案使用了 CheckBox
,但这超出了考虑范围。所以我决定自己编写。
Using the Code
步骤
- 添加新项目并选择 Web Forms ==> Web Forms 用户控件
- 输入名称并按“添加”按钮。
以下是 HTML 标记,其中使用了三个控件:ListBox
、LinkButton
和 ImageButton
。
<%@ 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
属性,用于在网页中使用该控件,例如,更改 Width
、Height
,设置显示文本,设置和获取选定的文本、值和项目。使用的控件 ListBox
和 LinkButton
也可供用户使用。您可以创建自定义事件。提供了 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>
您可以使用自己的 tagPrefix
和 tagName
。
然后在网页中编写以下标记
<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 中),您可以将多个值以表格形式发送到数据库,以进行 insert
、update
或 delete
操作。请参阅附加代码。享受使用此控件。
关注点
类型转换:string
无法转换为 ListItem
,但反之则可以。
LostFocus
事件不可直接使用。我们正在使用 blur
事件。
历史
这是第一个版本。我将根据情况提供新版本。