DropDownCheckList ASP.NET 服务器控件

分享于 

24分钟阅读

Web开发

  繁體

介绍

对于最终用户,DropDownCheckList 类似于 HTML <选择> 当单击时显示可用选项作为复选框。 当列出的选项超出显示宽度时,显示框列出了选中的选项,以及开发者定义的List 分隔符以及附加省略号或者其他文本的能力。 本文介绍了控件的常见属性和方法,并描述了从这个继承和面临的重要问题到子类 CheckBoxList的选择。 同时,还提出了通过客户端JavaScript解决的难题,包括必要时省略省略号,以及使用文档单击处理程序在外部出现的情况下自动执行。 后者和借用的shim 技术在开发自定义下拉网络控件时特别有用。

使用控件

DropDownCheckList 设计的客户端库旨在提供跨平台兼容性,至少与主流浏览器的现代版本兼容。 它已经被 IE 6专门测试过。 x,Netscape 7.x 和 8. x 和 Firefox 1.x。 JavaScript文件 DropDownCheckList.js 包含 DropDownCheckList的客户端对象定义。 要使用该控件,首先将文件 DropDownCheckList.js 复制到以下目录:

wwwrootaspnet_clientUNLV_IAP_WebControlsDropDownCheckList

有几个属性可以用于自定义控件的显示。 使用 DisplayBoxCssClass 和/或者 DisplayBoxCssStyle 属性为显示框指定CSS样式。 ,DisplayTextCssClassDisplayTextCssStyle 为显示文本指定CSS样式,CheckListCssClassCheckListCssStyle 表示复选框的CSS样式。

在显示框中呈现下拉图像取决于 DropImageSrcDropImagePosition 属性。 如果 DropImageSrc 为空,或者 DropImagePosition 设置为 NoImage,则在下拉框中不显示任何图像。 如果指定了 DropImageSrc,则图像的位置将为 LeftRight 或者 Both,如 DropImagePosition 所示。

DropDownCheckList的各种CSS样式和放置图像

控件的行为是通过几个附加属性定义的。 DropDownMode 属性决定清单显示的方式。 如果设置为 Inline,清单将在周围的HTML中展开。 如果设置为 OnTop 或者 OnTopWithShim,清单将绝对定位在其他HTML内容的顶部。 "shim"选项提供与 IE的兼容性;有关详细信息,请参阅使用 shim的。

Separator 属性表示用于分隔列出项目的字符。 DisplayTextWidth 指定显示选中选项的显示框中可用的最大宽度( 以像素为单位)。 当列出的选项超出这里宽度时,将截断文本并添加 TruncateString 属性。 通常,TruncateString 是一个省略号(。),但如果需要,可以设置为其他文本或者空字符串。 如果希望允许显示框展开而不是截断文本,请将 DisplayTextWidth 设置为 -1.

若要指示未选中选项时显示的文本,请将 TextWhenNoneChecked 属性设置为所需的字符串。 也可以通过将 DisplayTextList 属性设置为 Labels 或者 Values 来指定是否在显示框中列出复选框标签或者值( 分别为子 ListItemTextValue 属性)。

DisplayTextList 属性设置为 Values

作为 CheckBoxList的子类,DataSourceItems Collection 等数据绑定属性被继承。 在表单提交时,开发人员可以检查 Items Collection的选中复选框,就像使用 CheckBoxList 时一样。 DropDownCheckList 还公开了两个重载实用程序方法: SelectedLabelsToString()SelectedValuesToString() 每个都返回选定的项目,列出为单个连接字符串。 重载允许开发人员指定 List 分隔符和文本分隔符。

下面是一个完整的. aspx 页面示例,它使用 DropDownCheckList 控件演示了几个属性和两个 Selected... ToString() 方法:

<%@PageLanguage="c#"AutoEventWireup="true"%><%@RegisterTagPrefix="cc1"Namespace="UNLV.IAP.WebControls"Assembly="DropDownCheckList"%><scriptrunat="server">void Page_Load(object o, EventArgs e)
 {
 lblResults.Text = "";
 }
 void btnSubmit_Click(object o, EventArgs e)
 {
 string sLabels = dd.SelectedLabelsToString(",");
 string sValues = dd.SelectedValuesToString(",", "'");
 lblResults.Text = "Selected Items:" + sLabels
 + "<br/>" + "Values:" + sValues;
 }
 void btnClear_Click(object o, EventArgs e)
 {
 dd.SelectedValue = null;
 }</script><html><head><title>DropDownCheckList Sample</title><style>. boxStyle {
 border: 2px solid darkBlue;background-color: lightBlue;padding: 8px; }
 </style></head><body><formrunat="server"><h3>DropDownCheckList Sample</h3><p>Click the drop-down box to select options</p><cc1:DropDownCheckListid="dd"runat="server"RepeatColumns="2"DropImageSrc="dropImage.gif"DropImagePosition="Right"DropDownMode="OnTopWithShim"CheckListCssClass="boxStyle"CheckListCssStyle=""DisplayTextCssStyle="font-family: Tahoma;"DisplayTextWidth="180"DisplayTextList="Labels"Separator=","TruncateString="..."TextWhenNoneChecked="--select--"><asp:ListItemtext="North"value="N"/><asp:ListItemtext="South"value="S"/><asp:ListItemtext="East"value="E"/><asp:ListItemtext="West"value="W"/><asp:ListItemtext="Northeast"value="NE"/><asp:ListItemtext="Southeast"value="SE"/><asp:ListItemtext="Northwest"value="NW"/><asp:ListItemtext="Southwest"value="SW"/></cc1:DropDownCheckList><p><asp:Buttonid="btnSubmit"runat="server"text="Submit Choices"onClick="btnSubmit_Click"/><asp:Buttonid="btnClear"runat="server"text="Clear Choices"onClick="btnClear_Click"/></p><p><asp:Labelid="lblResults"runat="server"/></p></form></body></html>

从CheckBoxList继承

子类化 CheckBoxList 有正的和负面的结果。 另外,我们的DropDownCheckList 继承了支持数据绑定。Items Collection 和重复布局属性的CheckBoxList

在负方面,我们不能访问单个 CheckBox 控件,我们需要添加 Value 属性( 如果 DisplayTextList 设置为 Values,则需要),以及客户端 onclick 处理程序。 简单地说,CheckBoxList 没有将 CheckBox 控件作为子级集成,因这里我们缺少操作单个框的能力。 我们可以在客户端库中添加 onclick 处理程序,但是将 Value 属性添加到呈现的复选框中是必须被管理的服务器端。

为了在这个约束中工作,但是仍然利用 CheckBoxList的数据绑定和重复布局呈现,我们在重写的Render() 方法中执行了。 在为显示框生成必要的HTML之后,我们将呈现 <div> 复选框 List的标记。 如果不需要呈现 Value 属性,我们只需要根据输出流从基 CheckBoxList 执行 Render() 方法。 但是,如果需要呈现值,那么我们针对定制的HtmlTextWriter 执行 base.Render(),用 StringWriter 构造,而不是正常的输出流。 这样,我们就可以将呈现的List 作为规则 字符串 ,并操作它以插入我们自己的Value 属性。 下面显示了 Render() 中的相关代码:

protectedoverridevoid Render(HtmlTextWriter output)
{
. . . 
 // next, render the contents of the checkboxlist;// do we need to render values?if (_displayTextList == DisplayTextListEnum.Values)
 {
 // if so, we need to render to a string first// so we can include our own values attribute StringWriter sw = new StringWriter();
 HtmlTextWriter wr = new HtmlTextWriter(sw);
 base.Render(wr);
 string sHtml = sw.ToString();
 wr.Close();
 sw.Close();
 // now modify the code to include custom attributes sHtml = ModifyRenderedCheckboxes(sHtml);
 // and write to the output stream output.Write(sHtml);
 }
 else {
 // if we're not rendering custom value attributes,// just output the checkboxes to the output streambase.Render(output);
 }
. . . 
}

上面引用的方法 ModifyRenderedCheckboxes() 使用正则表达式来查找每个复选框,然后将适当的ListItem.Value 属性作为 Value 属性插入。

protectedstring ModifyRenderedCheckboxes(string sHtml)
{
 // use a regular expression to identify in the form://<input id="DropDownCheckList1_0" type="checkbox" string s = string.Format("input id="{0}_(?<" + 
 "index>d+)"s+type="checkbox"s+", 
 this.ClientID);
 Regex r = new Regex(s, RegexOptions.IgnoreCase);
 MatchCollection matches = r.Matches(sHtml);
 foreach (Match m in matches)
 {
 int index = Convert.ToInt32(m.Groups["index"].Value);
 sHtml = Regex.Replace(sHtml, m.Value, m.Value + " value="" 
 + this.Items[index].Value + """);
 }
 return sHtml;
}

客户端JavaScript中解决的挑战

控件的驱动目标之一是维护跨平台兼容性,至少与最近版本的IE ( 6.x )。Netscape ( 7.x 和 8. x ) 和 Firefox ( 1.x ) 保持一致。 这个目标影响了客户端脚本的几个方面。

( 关于 Netscape 6.x的说明: 所呈现的控件不能与 Netscape 6一起使用,这是一个重要原因。 Netscape 6不提交表单输入 <div> 使用 display 设置为 none - 所以当清单折叠时,它的复选框选择不会随它的他表单输入提交。 希望支持 Netscape 6的开发者可能希望尝试 visibility 属性作为 display 属性的替代项。

当显示文本太宽时附加省略号

由于可以向 List 显示比宽度更多的选中选项,因这里将指示器追加到截断文本很有用。 通常,在这种情况下使用省略号(。)。

IE 支持 text-overflow[^] 属性,它适当地可以设置为 ellipsis 不幸的是,这不是标准的,在 Firefox 和Netscape中不支持。 此外,IE 只支持省略号- 在截断字符串时不能自定义追加的文本。

为了确保支持 Firefox 和 Netscape,并允许自定义的TruncateString 属性,我们在客户端脚本文件中使用Prototype函数 DisplayCheckedItems(),定义如下:

function DDCL_DropDownCheckList_DisplayCheckedItems()
{
 var sLabel = "";
 var sCurrent = "";
 var sFull = "";
 var sBefore = "";
 var sCompText = "";
 var bEllipsisAdded = false;
 // get all checkboxes in the checklistvar e = this.divCheckboxes.getElementsByTagName("input");
 // clear the display textthis.divText.innerHTML = "";
 // clear the title (tooltip) attributethis.divDisplayBox.title = "";
 // loop through all checkboxes in the checklist to see // which ones are checked;for (var i=0; i<e.length; i++)
 {
 if (e[i].type == "checkbox" && e[i].checked)
 {
 // if the checkbox is checked, get its associated label textif (this.displayList == DDCL_DISPLAYTEXTLIST_LABELS)
 // get the label for the checkbox sLabel = this.GetLabelForCheckbox(e[i]);
 else// get the value for the checkbox sLabel = e[i].value;
 // add the list separator if necessaryif (sCurrent!= "")
 {
 sCurrent += this.separator;
 sFull += this.separator;
 }
 sFull += sLabel;
 sCurrent += sLabel;
 if (bEllipsisAdded == false)
 {
 // add this one to the text box, then test for the// width against the display boxthis.divText.innerHTML = "<nobr>" + sCurrent + "</nobr>";
 if (this.divText.offsetWidth> this.boundingBoxWidth 
 && this.allowExpand == false)
 {
 // too big; shrink by what we can and add the ellipsis // (or other trunacte string)while (this.divText.offsetWidth> this.boundingBoxWidth 
 && sCurrent.length> 0)
 {
 sCurrent = sCurrent.substr(0, sCurrent.length - 1);
 this.divText.innerHTML = "<nobr>" + sCurrent 
 + this.truncateString + "</nobr>";
 }
 // and indicate the ellipsis (or other truncate text) // has been added bEllipsisAdded = true;
 }
 }
 }
 }
 // finally, if there are no contents, display the textWhenNone messageif (this.divText.innerHTML == "")
 {
 if(this.textWhenNone == "")
 this.divText.innerHTML = "&nbsp;";
 elsethis.divText.innerHTML = this.textWhenNone;
 }
 // if we added the ellipsis, set the title attribute to the full string// (which will display as a tooltip in most browsers)if (bEllipsisAdded)
 this.divDisplayBox.title = sFull;
 elsethis.divDisplayBox.title = "";
}

对于每个复选框,它的标签或者值( 取决于服务器端属性 DisplayTextList ) 被添加到显示文本中 <span> 元素。这将导致 <span> 要增加的offsetWidth 属性,它将与边界元素的offsetWidth 进行比较( <div> 在其中显示文本 <span> 在构造函数中,我们以前将框的边界 offsetWidth 存储在 boundingBoxWidth 属性中。

这里脚本还引用了函数 GetLabelForCheckbox(),该函数用于确定 <标签> 渲染的文本对应的文本 <输入 type="复选框"> 对于选中的选项。

function DDCL_DropDownCheckList_GetLabelForCheckbox(elem)
 {
 var e = this.divCheckboxes.getElementsByTagName("label");
 for (var i=0; i<e.length; i++)
 {
 if (e[i].htmlFor == elem.id)
 {
 for (var j=0; j<e[i].childNodes.length; j++)
 {
 if (e[i].childNodes[j].nodeType == 3) //text type {
 return e[i].childNodes[j].nodeValue;
 }
 }
 }
 }
 // still here? no <label> for this checkbox thenreturnnull;
 }

允许在清单外单击以显示列表

在显示框中单击将扩大清单。 在这个控件的第一个版本中,需要再次单击显示框中的collapse。 这很快就成了一个令人烦恼的问题,因为我觉得自己在清单旁边单击( 潜意识的) List collapse。 也许这只是我的固定,但是这个控件可以在单击列表之外自动折叠 List的功能。

为了实现这一点,客户端构造函数向文档添加一个 click 事件处理程序。 它使用 document.attachEvent() ( 在 IE 中支持) 或者 document.addEventListener() ( 在Mozilla中支持) 来维护任何现有的文档 click 事件处理程序。 构造函数中的相关代码如下:

function DDCL_DropDownCheckList(...)
{
. . . 
 // if the browser supports bubbling events, install a default click// handler for the document too, that will close the checkboxes div// if there is a click outside itif (document.attachEvent)
 {
 document.attachEvent('onclick', function() { eval("DDCL_HandleDocumentClick('" + id + "');") }
 );
 }
 elseif (document.addEventListener)
 {
 document.addEventListener('click', function() { eval("DDCL_HandleDocumentClick('" + id + "');") }
, false);
 } 
. . . 
}

这样添加到 document的事件将以冒泡方式触发,这意味着 document 将是处理事件的最后一个对象。 如果在我们的一个复选框中发生了点击,那么在文档获取之前,它会获得一个。 这非常有用,因为它为我们提供了指示在复选框中出现点击的功能 divdocument 处理程序应该忽略它。

复选框的click 处理程序 divinCheckboxDiv 属性设置为 true。 然后由我们的自定义 document.click 处理程序测试,以确定是否对清单进行 collapse 处理。

function DDCL_HandleDocumentClick(id)
{
 var obj = DDCL_GetObject(id);
 if (obj)
 {
 if (obj.inCheckboxDiv == true)
 obj.inCheckboxDiv = false;
 else obj.CloseCheckList(); 
 }
}

使用 shim 进行 IE

自定义 <div> 绝对定位在其他控件之上的部分演示了一个相当不幸的问题,但在 IE 中有很好的文档化行为。 窗口控件,包括正常跌落和ActiveX控件,将显示在 <div> ,覆盖 <div> with s的内容。 无论使用的是什么 z-index,都会发生这种情况 <div>

iPhone 7 还没出来,我们已经在iPhone上获取细节 8,或者不管是想到下一步。 <选择> 框中显示的框 <div> 在 IE 中。

一个常见的解决方法是使用JavaScript循环遍历所有 <选择> 文档中的对象,将每个对象的display 设置为 none,或者将每个对象的visibility 设置为 hidden。 从最终用户角度看,我从来不会对这个解决方案造成一些非常奇怪的显示行为。

幸运的是,Joe为Coalesys工作,为 IE 版本开发了不同的解决方案,该解决方案适用于版本 5.5和更高版本的 [1]。 技术使用"垫片"的形式的<iframe>,它的中 z-index的LESS 比的z-index 要高。 <div> 窗口控件仍将显示在 <div> 在版本 5.5中,<iframe> 位置绝对会显示在窗口控件的顶部。 所提供的解决方案是在任何窗口控件的顶部显示一个 shim <iframe>,并将它的放下。 <div><iframe>的顶部。

如果 DropDownCheckListDropDownMode 设置为 OnTopWithShim,则它将呈现此类 <iframe>。 然后,shim 随清单一起显示 <div> 通过客户端Prototype方法 OpenCheckList():

function DDCL_DropDownCheckList_OpenCheckList()
{
 // open the checkboxlist; first, position it below the displaybox// determine the position based on the dropDownModeif (this.dropDownMode == DDCL_DROPDOWNMODE_INLINE)
 {
 // inline mode; we're already setup as we need to bethis.divCheckboxes.style.display = "block";
 }
 else {
 // on top modes; position the boxthis.divCheckboxes.style.left = DDCL_findPosX(this.divDisplayBox);
 this.divCheckboxes.style.top = DDCL_findPosY(this.divDisplayBox) 
 + this.divDisplayBox.offsetHeight;
 this.divCheckboxes.style.display = "block";
 // if we want the shim, apply that nowif (this.dropDownMode == DDCL_DROPDOWNMODE_ONTOPWITHSHIM)
 {
 this.shim.style.width = this.divCheckboxes.offsetWidth;
 this.shim.style.height = this.divCheckboxes.offsetHeight;
 this.shim.style.top = this.divCheckboxes.style.top;
 this.shim.style.left = this.divCheckboxes.style.left;
 this.shim.style.zIndex = this.divCheckboxes.style.zIndex - 1;
 this.shim.style.display = "block";
 }
 }
}

I peter [2] referenced。

摘要

DropDownCheckList 是一个 ASP.NET 控件,它在自定义下拉列表中将复选框显示为选项。 尽管有几个属性被公开为定义行为和样式,但是用户与控件的交互通过客户端JavaScript库进行管理。 这包括省略或者它的他文本的应用,因为列出的选项对于显示框太宽,自动折叠。 通过使用文档事件处理程序来自动崩溃,为 IE 兼容性提供shim技术,提供了改进用户体验以提高用户体验的例子。

确认


相关文章