在 ASP.NET 中,创建多列组合框

分享于 

17分钟阅读

Web开发

  繁體

介绍

以前我遇到了一个要求,提供类似于传统组合框( 在 Windows 窗体中找到) 和 ASP.NET的组合框功能。 我在网上搜索了很多,但找不到适合我需求的东西。 所以我决定从头开始写自己的控件,这就是我所谓的multicolumn组合框。 它是一个组合框,但有多个列和一个文本框。 你可以通过在文本框中键入键列值来搜索特定行。

snap below 显示了多列组合框的工作。 第一列是我们基于搜索的键列。 在本例中,是项代码。 键入 textbox 9 shows shows starting starting starting item,然后在项目 code move move move mouse mouse,然后 textbox reflects reflects reflects。 在搜索文本框中键入数据时,自动智能感知将自动打开。 你可以通过单击搜索文本框右侧的按钮来显式打开搜索智能感知。

当搜索文本框为空并且显式单击按钮时,所有项都将显示为你在 snap below 中看到的。 主要的目标是用户可以看到数据。

要小心 ! 当使用

使用多列组合框时,删除位于搜索感知器高度的所有控件的z-index。 还需要在 DropdownList 控件位于搜索智能感知的高度内时进行注意。 DropdownList 始终位于顶部,无论你设置了什么 z-index。 这就是 DropdownList 在 Windows 中的实现方式。 在提供的示例中,我模拟了相同的操作。 我使用两个下拉列表 below,并将多列组合框隐藏在多列组合框的ControlsToHide 属性中。

<ControlsToHide><cc1:HiddenControlControlId="DropDownList1"></cc1:HiddenControl><cc1:HiddenControlControlId="DropDownList2"></cc1:HiddenControl></ControlsToHide>

由于这里属性,DropDownList1DropDownList2 在显示多列组合框时都是不可见的。

你可以使用我在设计模式中提供的Collection 编辑器来设置这个属性。

只有在高度内有下拉 List 时,才必须执行这里步骤。 ( 文本框和其他控件都很好。 虽然我提供了一个通用模型,如果有任何控制干扰你,通过提到它的ID来退出游戏它不是一个 Bug,而是 DropdownList 控件实现的方式。 我已经在我的控制中治愈了这个 Bug。 你可以看到许多站点拥有这个公共 Bug。 如果不执行这里步骤,将看到如下所示的输出:

属性

  • Columns

    要在多列组合框 List 中显示的列。 记住键列应该是多列组合框中的第一列,否则multicolumn组合框将触发JavaScript错误。 你可以通过使用我提供的JavaScript源来更改这里行为。 此外,只允许使用一个键列。 否则,只允许引发一个键列的异常。

    <Columns><cc1:ColumnHeaderText="Item Code"KeyColumn="True"DataField="PKID"ColumnWidth="10%"></cc1:Column><cc1:ColumnHeaderText="Item Name"KeyColumn="False"DataField="Name"ColumnWidth="80%"></cc1:Column><cc1:ColumnHeaderText="UnitCost"KeyColumn="False"DataField="UnitCost"ColumnWidth="10%"></cc1:Column></Columns>

    你可以从 Columns 属性 Collection 编辑器设置这里属性。

  • AutoPostBack

    这里属性指示单击多列组合框中的项时是否激发 postback。 如果这是 true,它会激发一个 RowSelectionChanged 事件,该事件在aspx页中捕获,如下所示:

    在示例示例中,我通过编写如下代码捕获了 auto postback 事件:

    txtName.Text = args.Cells[1].ToString();//item name column

    你可以通过索引 Cells 属性来连续获取单元格的值,因为它使用 ArrayList 类。 例如:

    args.Cells[0].ToString();//item codeargs.Cells[1].ToString();//item nameargs.Cells[2].ToString();//unit cost
  • ItemMouseOverColor

    当鼠标移动到项目上时使用的颜色。

  • GridLinesColor

    搜索网格的网格线颜色。

  • DownArrowButtonHeight

    向下箭头按钮的高度。

  • DownArrowButtonWidth

    向下箭头按钮宽度。

  • ValidatorErrorMessage

    如果没有在搜索文本框中输入数据,将显示的错误消息。

  • ValidatorText

    验证程序的文本。

  • ValidatorDisplayStyle

    验证程序在页上的呈现方式。

  • ValidatorEnabled

    如果要在搜索文本框中使用所需的字段验证,请在 true ,否则, false

  • ValidatorTooltip

    验证器中要显示的工具提示。

  • ComboBoxListHeight

    智能感知的高度。

  • ComboBoxListWidth

    智能感知的宽度。

  • TextBoxWidth

    搜索数据文本框的宽度。

  • ValidatorCSS

    所需验证程序的CSS类。

  • HeaderCSS

    网格标题的CSS类。

  • ItemsCSS

    网格项的CSS类。

  • DownArrowButtonCSS

    向下箭头按钮的CSS类。

  • TextBoxCSS

    搜索数据文本框的CSS类。

  • HorizontalScrolling

    是否使用水平滚动或者不使用。

  • VerticalScrolling

    是否使用垂直滚动或者不使用。

  • ControlsToHide

    所有这些控件的控件id可能出现在multicolumn组合框( 例如 DropdownList 控件) of。 你可以使用这里属性指定所有这些控件的id。

    <ControlsToHide><cc1:HiddenControlControlId="DropDownList1"></cc1:HiddenControl><cc1:HiddenControlControlId="DropDownList2"></cc1:HiddenControl></ControlsToHide>

数据验证支持

内部组合框内部使用 RequiredFieldValidator 来验证数据。 你可以通过设置验证程序属性来启用或者禁用验证。 默认情况下,禁用验证。

单击Post按钮时,你将看到验证将按如下所示操作:

多列组合框的工作方式

multicolumn组合框是一个复合服务器控件,它在它的CreateChildControls() 方法中创建一个子服务器控件。 这里方法通知服务器控件创建包含在其中的任何子控件。 在实现复合控件时,必须执行以下两个关键任务:

  • 重写 CreateChildControl 方法实例化子控件,初始化它们并将它们添加到父层次结构的控件中。
  • 实现 INamingContainer 接口,该接口在你的控制下创建一个新的命名范围。
PublicClass MultiColumnComboBox _
 Inherits System.Web.UI.WebControls.WebControl _
 Implements INamingContainer

现在让我们来讨论什么是命名作用域? 这个概念类似于 C++ 和 C# 中命名空间的概念。 对于 比如,在. NET 框架中,DataSet 类位于 System.Data 命名空间中。 不引用 System.Data 命名空间,就不能直接访问它。 同样的规则适用于多列组合框和所有复合服务器控件。 例如,当多列组合框搜索文本框呈现在浏览器上时,它会生成像 MultiColumnComboBox1:txtData 这样的客户端。 这个ID告诉 txtDataMultiColumnComboBox1的范围内,它是父服务器控件的ID。

你不需要生成这里标识,因为 INamingContainer 自动为你执行这里操作。 实现这里接口时,它为服务器控件创建一个新的命名作用域,并为所有子控件生成一个唯一的标识。 因此,如果在aspx页上使用了两个multicolumn组合框实例,则会遇到如下内容:

MultiColumnComboBox1:txtData
MultiColumnComboBox2:txtData

尝试删除 INamingContainer 接口并观察它的效果。

现在是 CreateChildControl() 方法。 在它中,我创建了所有的子控件。 行 Controls.Clear() 确保子控件的多个副本不会添加到服务器控件的Controls Collection 中。 剩下的是非常自我解释的。

Controls.Clear()''----Data Text boxWith txtData
. ID = "txtData"IfNotMe.ViewState("TextBoxWidth") IsNothingThen. Width = Me.ViewState("TextBoxWidth")
 EndIfIfNotMe.ViewState("TextBoxCSS") IsNothingThen. CssClass = Me.ViewState("TextBoxCSS")
 EndIfEndWith''---Down Arrow ButtonbtnDownArrow = New HtmlInputButtonWith btnDownArrow
. ID = "btnDownArrow"IfNotMe.ViewState("DownArrowButtonWidth") IsNothingThen. Style("Width") = Me.ViewState("DownArrowButtonWidth").ToString()
 EndIfIfNotMe.ViewState("DownArrowButtonHeight") IsNothingThen. Style("height") = Me.ViewState("DownArrowButtonHeight").ToString()
 EndIfIfNotMe.ViewState("DownArrowButtonCSS") IsNothingThen. Attributes("class") = Me.ViewState("DownArrowButtonCSS")
 EndIfEndWith''----Required Field ValidatorIfNotMe.ViewState("ValidatorEnabled") IsNothingAndAlso _
 Me.ViewState("ValidatorEnabled") = TrueThen rfData = New RequiredFieldValidator
 With rfData
. ControlToValidate = txtData.ID
 IfMe.ViewState("ValidatorErrorMessage") IsNothingThen. ErrorMessage = "Please Enter Data"Else. ErrorMessage = Me.ViewState("ValidatorErrorMessage")
 EndIfIfMe.ViewState("ValidatorText") IsNothingThen. Text = "*"Else. Text = Me.ViewState("ValidatorText")
 EndIfIfNotMe.ViewState("ValidatorDisplayStyle") IsNothingThen. Display = Me.ViewState("ValidatorDisplayStyle")
 Else. Display = ValidatorDisplay.None
 EndIfIfNotMe.ViewState("ValidatorCSS") IsNothingThen. CssClass = Me.ViewState("ValidatorCSS")
 EndIfEndWithEndIf''----Data Grid-----dgSearch = New DataGridWith dgSearch
. ID = "dgSearch". BorderWidth = New Unit(1)
. GridLines = GridLines.Both
. Width = New Unit("100%")
 IfNotMe.ViewState("HeaderCSS") IsNothingThen. HeaderStyle.CssClass = Me.ViewState("HeaderCSS")
 EndIfIfNotMe.ViewState("ItemsCSS") IsNothingThen. ItemStyle.CssClass = Me.ViewState("ItemsCSS")
 EndIfIfNotMe.ViewState("GridLinesColor") IsNothingThen. BorderColor = Me.ViewState("GridLinesColor")
 Else. BorderColor = Color.Black
 EndIfEndWith

代码的后面部分对于大多数开发人员来说是一个野兽。 现在让我们吃掉这个野兽。 我以编程方式为 ASP.NET DataGrid 创建动态模板列。 通常我们在设计模式中设置模板列,但是在这种情况下,我们为 ASP.NET DataGrid 创建动态模板列。 编程创建时,应实现如下所示的ITemplate 接口:

FriendClass SearchGridTemplateColumn _
 Implements ITemplate

在实例化方法中,我将链接按钮添加到控件层次结构中。 接下来是将链接按钮与数据源绑定起来。 为此,我执行以下操作:

AddHandler lk.DataBinding, AddressOf DataBind

我在这里做的是设置 LinkButtonDataBinding 事件的事件处理程序。 在编写 dgSearch.DataBind() 时调用,后者又调用所有子控件的DataBinding 事件。

PublicSub InstantiateIn(ByVal container As System.Web.UI.Control) _
 Implements System.Web.UI.ITemplate.InstantiateIn
 Dim lk As LinkButton
 SelectCase templateType
 Case ListItemType.Header
 Case ListItemType.Footer
 Case ListItemType.Item
 lk = New LinkButton
 AddHandler lk.DataBinding, AddressOf DataBind
 lk.ID = ctrlId
 'lkSelect.CommandName ="Select" container.Controls.Add(lk)
 EndSelectEndSub

现在代码中出现了更讨厌的部分。 用另一种方法,我对语句进行动态编码,比如 <%# databinder。评估(,。dataitem"mycolumn") %> 当显示数据时,只能显示每一行的一个版本。 显示的行是一个 DataRowView。 在源代码 below 中,我使用语句获取 LinkButtonNamingContainerCType(lk.NamingContainer, DataGridItem) 它是 DataGridItem的一个实例。 我在 DataGrid的每一行呈现 LinkButton,在渲染过程中,我需要知道每个 LinkButton。 变量 dgi ( dgi 出现在下面的源代码中) 提供了 DataGrid的单个项,并且我引用了 DataGrid 数据源的单个项。 子语句 Row.Item(Me.columnName ) 实际上是指 DataGrid的每一列中呈现的行的值。

ProtectedSub DataBind(ByVal sender AsObject, ByVal e As EventArgs)
 Dim lk As LinkButton
 lk = CType(sender, LinkButton)
 Dim dgi As DataGridItem
 dgi = CType(lk.NamingContainer, DataGridItem)
 lk.Text = CType(CType(dgi.DataItem, _
 DataRowView).Row.Item(Me.columnName), String)EndSub

现在我们回到 CreateChildControls() 方法。 每当在 DataGrid 中以编程方式添加模板列时,始终要创建 TemplateColumn 类的实例。

Dim enmDataSource As IEnumerator = dtSource.GetList().GetEnumerator()
 Dim enmColumns As IEnumerator = Columns.GetEnumerator
 Dim tc As TemplateColumn
 Dim bc As BoundColumn
 Dim col As Column
 Dim keyColCount AsInteger = 0While enmColumns.MoveNext
 If keyColCount> 1ThenThrowNew Exception("Only one key column is allowd")
 EndIf col = CType(enmColumns.Current, Column)
 Dim lkColId AsStringIfNot col.KeyColumn Then'bc = New BoundColumn'bc.DataField = col.DataField'bc.HeaderText = col.HeaderText'bc.HeaderStyle.Wrap = False'If col.ColumnWidth.ToString().Length> 0 Then' bc.ItemStyle.Width = col.ColumnWidth'End If'dgSearch.Columns.Add(bc) lkColId = "lk" & col.DataField
 tc = New TemplateColumn
 tc.ItemTemplate = _
 New SearchGridTemplateColumn(ListItemType.Item, _
 col.DataField, lkColId)
 tc.HeaderText = col.HeaderText
 tc.HeaderStyle.Wrap = FalseIf col.ColumnWidth.ToString().Length> 0Then tc.ItemStyle.Width = col.ColumnWidth
 EndIf dgSearch.Columns.Add(tc)
 Else tc = New TemplateColumn
 tc.ItemTemplate = _
 New SearchGridTemplateColumn(ListItemType.Item, _
 col.DataField)
 tc.HeaderText = col.HeaderText
 tc.HeaderStyle.Wrap = FalseIf col.ColumnWidth.ToString().Length> 0Then tc.ItemStyle.Width = col.ColumnWidth
 EndIf dgSearch.Columns.Add(tc)
 keyColCount += 1EndIfEndWhile dgSearch.AutoGenerateColumns = False dgSearch.DataSource = dtSource
 dgSearch.DataBind()EndIf

COM  asp  asp-net  BOX  multicol  
相关文章