Click here to Skip to main content
15,890,579 members
Articles / Web Development / ASP.NET
Article

Creating a Multicolumn Combo Box in ASP.NET

Rate me:
Please Sign up or sign in to vote.
4.62/5 (17 votes)
29 Sep 20057 min read 305.7K   6.6K   89   86
Creating a multicolumn combo box in ASP.NET.

Introduction

Previously I came across a requirement to provide a functionality of something similar to a traditional combo box (found in Windows Forms) and a sort of multicolumn combo box in ASP.NET. I searched a lot on the net but found nothing suitable for my requirements. So, I decided to write my own control from scratch and here is what I call a multicolumn combo box. It is a combo box but with multiple columns and a textbox. You can search a particular row by typing the key column value in the textbox.

The snap below shows the working of the multicolumn combo box. The first column is the key column on which we base our search. In this case it is the Item Code. When I type 9 in the textbox it shows all entries having item code starting with digit 9, and when I move my mouse over any item, for example, over an entry having item code 93, then the textbox reflects the current item code. The Search intellisense automatically opens when you type data in the search textbox. You can explicitly open Search intellisense by clicking the button on the right side of the search textbox.

Image 1

Image 2

When the search textbox is empty and you explicitly click the button then all items will be shown as you can see in the snap below. The main objective is that the user can see the data.

Image 3

A Care to be taken! When using

When using the multicolumn combo box, remove z-index of all the controls which lie in the height of the Search intellisense. Care also need to be taken when the DropdownList control lies within the height of the Search intellisense. DropDownList resides always on top irrespective of what z-index you set. That’s how the DropDownList is implemented in Windows. In the sample provided, I simulate the same action. I use two dropdown lists below the multi column combo box and hide them through the ControlsToHide property of the multi column combo box.

HTML
<ControlsToHide>
  <cc1:HiddenControl ControlId="DropDownList1"></cc1:HiddenControl>
  <cc1:HiddenControl ControlId="DropDownList2"></cc1:HiddenControl>
</ControlsToHide>

Thanks to this property, both DropDownList1 and DropDownList2 will be invisible when the multicolumn combo box is shown.

You can set this property using a collection editor which I provided in design mode.

Image 4

You have to do this step only if you have the drop down list within the height. (Text box and other controls are fine. Although, I have provided a generic model, if any control disturbs you, shoot that control out of the game by mentioning its ID!) It’s not a bug but the way the DropdownList control is implemented. I have cured this bug in my control. You can see many sites having this common bug. If you don’t do this step, you will see an output like this:

Image 5

Properties

  • Columns

    The columns to be shown in the multicolumn combo box list. Remember that the key column should be the first column in the multicolumn combo box otherwise the multicolumn combo box will fire a JavaScript error. You can change this behavior by playing with my provided JavaScript source. Moreover, only one key column is allowed. Otherwise an exception of Only one key column is allowed is thrown.

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

    You can set this property from the Columns property collection editor.

    Image 6

  • AutoPostBack

    This property indicates whether to fire postback when the item in the multicolumn combo box is clicked or not. If this is true it fires an event of RowSelectionChanged which is captured in the aspx page like that:

    In my sample example, I have captured the auto postback event by writing code like this:

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

    You can successively get the values of cells by indexing the Cells attribute because it uses the ArrayList class. For example:

    C#
    args.Cells[0].ToString();//item code
    args.Cells[1].ToString();//item name
    args.Cells[2].ToString();//unit cost
  • ItemMouseOverColor

    The color to use when the mouse moves on the items.

  • GridLinesColor

    The grid lines color of the search grid.

  • DownArrowButtonHeight

    The height of the down arrow button.

  • DownArrowButtonWidth

    The down arrow button width.

  • ValidatorErrorMessage

    The error message to be shown if no data is entered into the search textbox.

  • ValidatorText

    The text of the validator.

  • ValidatorDisplayStyle

    How the validator is rendered on the page.

  • ValidatorEnabled

    If you want to use required field validation on the search text box then enable it by making this true, otherwise false.

  • ValidatorTooltip

    The tool tip to be shown in the validator.

  • ComboBoxListHeight

    The height of the intellisense.

  • ComboBoxListWidth

    The width of the intellisense.

  • TextBoxWidth

    The width of the search data text box.

  • ValidatorCSS

    The CSS class of the required validator.

  • HeaderCSS

    The CSS class of the grid header.

  • ItemsCSS

    The CSS class of grid items.

  • DownArrowButtonCSS

    The CSS class of the down arrow button.

  • TextBoxCSS

    The CSS class of the search data text box.

  • HorizontalScrolling

    Whether to use horizontal scrolling or not.

  • VerticalScrolling

    Whether to use vertical scrolling or not.

  • ControlsToHide

    The control IDs of all those controls which might appear on top of the multicolumn combo box (for example, the DropDownList control). You can specify the IDs of all those controls using this property.

    HTML
    <ControlsToHide>
      <cc1:HiddenControl ControlId="DropDownList1"></cc1:HiddenControl>
      <cc1:HiddenControl ControlId="DropDownList2"></cc1:HiddenControl>
    </ControlsToHide>

Data Validation Support

The multicolumn combo box internally uses the RequiredFieldValidator for validating data. You can enable or disable the validation by setting the validator properties. By default, the validation is disabled.

Image 7

When you click the Post button, you will see that the validation will be in action as shown below:

Image 8

How the multicolumn combo box works

The multicolumn combo box is a composite server control which creates a child server control in its CreateChildControls() method. This method notifies the server control to create any child control contained in it. There are two key tasks that you must perform when implementing a composite control:

  • Override the CreateChildControl method to instantiate child controls, initialize them and add them to the parent's controls hierarchy.
  • Implement the INamingContainer interface, which creates a new naming scope under your control.
VB
Public Class MultiColumnComboBox _
       Inherits System.Web.UI.WebControls.WebControl _
       Implements INamingContainer

Now let’s discuss what is a naming scope? This concept is similar to the concept of namespaces in C++ and C#. For e.g., in the .NET Framework, the DataSet class lives in the System.Data namespace. You can’t access it directly without referring the System.Data namespace. The same rule applies to the multicolumn combo box and all composite server controls. For example, when the multicolumn combo box search text box renders on your browser, it generates the client ID like MultiColumnComboBox1:txtData. This ID tells that txtData lives within the scope of MultiColumnComboBox1 which is the ID of the parent server control.

You don’t need to generate this ID because INamingContainer does this for you automatically. When implementing this interface it creates a new naming scope for server controls and generates a unique ID for all child controls. So if you are using two instances of the multicolumn combo box on your aspx page, you will encounter something like:

MultiColumnComboBox1:txtData
MultiColumnComboBox2:txtData

Try removing the INamingContainer interface and observe its effect.

Now comes the CreateChildControl() method. In it I have created all my child controls. The line Controls.Clear() ensures that multiple copies of child controls are not added to the Controls collection of the server control. The rest is very much self explanatory.

VB
Controls.Clear()

''----Data Text box
With txtData
    .ID = "txtData"

    If Not Me.ViewState("TextBoxWidth") Is Nothing Then
        .Width = Me.ViewState("TextBoxWidth")
    End If

    If Not Me.ViewState("TextBoxCSS") Is Nothing Then
        .CssClass = Me.ViewState("TextBoxCSS")
    End If
End With

''---Down Arrow Button
btnDownArrow = New HtmlInputButton

With btnDownArrow

    .ID = "btnDownArrow"

    If Not Me.ViewState("DownArrowButtonWidth") Is Nothing Then
        .Style("Width") = Me.ViewState("DownArrowButtonWidth").ToString()
    End If

    If Not Me.ViewState("DownArrowButtonHeight") Is Nothing Then
        .Style("height") = Me.ViewState("DownArrowButtonHeight").ToString()
    End If

    If Not Me.ViewState("DownArrowButtonCSS") Is Nothing Then
        .Attributes("class") = Me.ViewState("DownArrowButtonCSS")
    End If
End With

''----Required Field Validator
If Not Me.ViewState("ValidatorEnabled") Is Nothing AndAlso _
    Me.ViewState("ValidatorEnabled") = True Then

    rfData = New RequiredFieldValidator

    With rfData
        .ControlToValidate = txtData.ID

        If Me.ViewState("ValidatorErrorMessage") Is Nothing Then
          .ErrorMessage = "Please Enter Data"
        Else
          .ErrorMessage = Me.ViewState("ValidatorErrorMessage")
        End If

        If Me.ViewState("ValidatorText") Is Nothing Then
          .Text = "*"
        Else
          .Text = Me.ViewState("ValidatorText")
        End If

        If Not Me.ViewState("ValidatorDisplayStyle") Is Nothing Then
          .Display = Me.ViewState("ValidatorDisplayStyle")
        Else
          .Display = ValidatorDisplay.None
        End If

        If Not Me.ViewState("ValidatorCSS") Is Nothing Then
          .CssClass = Me.ViewState("ValidatorCSS")
        End If
     End With
End If

''----Data Grid-----
dgSearch = New DataGrid

With dgSearch
      .ID = "dgSearch"
      .BorderWidth = New Unit(1)
      .GridLines = GridLines.Both
      .Width = New Unit("100%")

      If Not Me.ViewState("HeaderCSS") Is Nothing Then
        .HeaderStyle.CssClass = Me.ViewState("HeaderCSS")
      End If

      If Not Me.ViewState("ItemsCSS") Is Nothing Then
        .ItemStyle.CssClass = Me.ViewState("ItemsCSS")
      End If

      If Not Me.ViewState("GridLinesColor") Is Nothing Then
        .BorderColor = Me.ViewState("GridLinesColor")
      Else
        .BorderColor = Color.Black
      End If
End With

The later part of the code is a wild beast for most of the developers. Now let's eat this beast. I programmatically create dynamic template columns for the ASP.NET DataGrid. Normally we set template columns in design mode but in this case we create dynamic template columns for the ASP.NET DataGrid. When programmatically creating, you should implement the ITemplate interface like this:

VB
Friend Class SearchGridTemplateColumn _
     Implements ITemplate

In the instantiation method I add the link button to the control hierarchy. The next thing is to bind the link button with the data source. For this purpose, I do this:

VB
AddHandler lk.DataBinding, AddressOf DataBind

What I am doing here is setting the event handler of the DataBinding event of the LinkButton. This is called when you write dgSearch.DataBind() which in turn calls the DataBinding events of all child controls.

VB
Public Sub InstantiateIn(ByVal container As System.Web.UI.Control) _
                      Implements System.Web.UI.ITemplate.InstantiateIn

    Dim lk As LinkButton

    Select Case 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)
    End Select
End Sub

Now comes a more nasty part of the code. Take it another way that I am doing dynamic coding for statements like <%# DataBinder.Eval(Container.DataItem,”MyColumn”)%>. Whenever data is displayed (for example, in a DataGrid control), only one version of each row can be displayed. The displayed row is a DataRowView. In the source code below, I am getting the NamingContainer of the LinkButton with the statement CType(lk.NamingContainer, DataGridItem) which is an instance of DataGridItem. I am rendering the LinkButton in each row of the DataGrid and in the rendering process I need to know about every LinkButton. The variable dgi (dgi is present in the source code below) gives me a single item of the DataGrid and with it I refer an individual item of the data source of DataGrid. The sub statement Row.Item(Me.columnName) actually refers to the value of that row which is rendered in each column of the DataGrid.

VB
Protected Sub DataBind(ByVal sender As Object, 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)
End Sub

Now we come back to the CreateChildControls() method. Whenever adding template columns programmatically in the DataGrid, always create an instance of the TemplateColumn class.

VB
    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 As Integer = 0

    While enmColumns.MoveNext
        If keyColCount > 1 Then
            Throw New Exception("Only one key column is allowd")
        End If

        col = CType(enmColumns.Current, Column)
        Dim lkColId As String

        If Not 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 = False

            If col.ColumnWidth.ToString().Length > 0 Then
                tc.ItemStyle.Width = col.ColumnWidth
            End If

            dgSearch.Columns.Add(tc)
        Else
            tc = New TemplateColumn
            tc.ItemTemplate = _
               New SearchGridTemplateColumn(ListItemType.Item, _
               col.DataField)
            tc.HeaderText = col.HeaderText
            tc.HeaderStyle.Wrap = False

            If col.ColumnWidth.ToString().Length > 0 Then
                tc.ItemStyle.Width = col.ColumnWidth
            End If

            dgSearch.Columns.Add(tc)
            keyColCount += 1
        End If
    End While

    dgSearch.AutoGenerateColumns = False
    dgSearch.DataSource = dtSource
    dgSearch.DataBind()
End If

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior)
Pakistan Pakistan
I love Karachi specially in the weather when there is no sun shine.I have masters degree in Computer Scince from University of Karachi(htpp://csku.edu.pk).When not playing with technology I sleep a lot and don't want from any one to even bother me!You, should't event think about that!!!!
I love my mother and she is the ultimate goal of my life.

Comments and Discussions

 
Questionadd events like onSelectedIndexChanged? Pin
dsmportal24-Apr-07 16:13
dsmportal24-Apr-07 16:13 
Generalhow do i add: HeaderTemplate/ [modified] Pin
dsmportal18-Apr-07 14:51
dsmportal18-Apr-07 14:51 
Questioncan't able to hide controls Pin
Member 25323465-Mar-07 18:41
Member 25323465-Mar-07 18:41 
AnswerRe: can't able to hide controls Pin
Tahir 11116-Mar-07 0:43
Tahir 11116-Mar-07 0:43 
GeneralAuto-Fill not working Pin
shilpa apte26-Feb-07 6:05
shilpa apte26-Feb-07 6:05 
QuestionIE7 Compatibility?? Pin
dougBR29-Dec-06 3:45
dougBR29-Dec-06 3:45 
AnswerRe: IE7 Compatibility?? Pin
Tahir 11126-Feb-07 20:13
Tahir 11126-Feb-07 20:13 
Newsnew Property for control Pin
Ronsolo7777-Sep-06 13:52
Ronsolo7777-Sep-06 13:52 
hello i add three Property to the control

HorizontalAlign
DataFormatField
Visible

i modified two class column and MultiColumnComboBox


---------------------------------------------------
---------------------------------------------------
-------------------column class--------------------
---------------------------------------------------
---------------------------------------------------
Imports System.ComponentModel
Imports System.ComponentModel.Design ' Custom Designers Require this NameSpace
Imports System.Drawing.Design ' Designers Are in this NameSpace, You Also need to a reference to System.Design.Dll
Imports System.Web.UI.WebControls

#Region "multi column combobox column class"
''
''this class actually represent multicolumncombox individual column.
''

<typeconverter(gettype(expandableobjectconverter))> _
Public Class Column
Private colHeaderText As String
Private colWidth As Unit
Private colDataField As String
Private colDataFormatField As String
Private isKeyColumn As Boolean
Private bVisible As Boolean = True
Private colAling As System.Web.UI.WebControls.HorizontalAlign

Public Sub New()
End Sub

<notifyparentproperty(true), category("appearance")=""> _
Public Property HeaderText() As String
Get
Return colHeaderText
End Get
Set(ByVal Value As String)
colHeaderText = Value
End Set
End Property

<notifyparentproperty(true), defaultvalue(""),="" category("appearance")=""> _
Public Property ColumnWidth() As Unit
Get
Return colWidth
End Get
Set(ByVal Value As Unit)
colWidth = Value
End Set
End Property

<notifyparentproperty(true), category("data")=""> _
Public Property DataField() As String
Get
Return colDataField
End Get
Set(ByVal Value As String)
colDataField = Value
End Set
End Property


<notifyparentproperty(true), category("data")=""> _
Public Property KeyColumn() As Boolean
Get
Return isKeyColumn
End Get
Set(ByVal Value As Boolean)
isKeyColumn = Value
End Set
End Property


<notifyparentproperty(true), category("appearance")=""> _
Public Property Visible() As Boolean
Get
Return bVisible
End Get
Set(ByVal Value As Boolean)
bVisible = Value
End Set
End Property

<notifyparentproperty(true), category("appearance")=""> _
Public Property DataFormatField() As String
Get
Return colDataFormatField
End Get
Set(ByVal Value As String)
colDataFormatField = Value
End Set
End Property


'colAling
<notifyparentproperty(true), category("appearance")=""> _
Public Property HorizontalAlign() As System.Web.UI.WebControls.HorizontalAlign
Get
Return colAling
End Get
Set(ByVal Value As System.Web.UI.WebControls.HorizontalAlign)
colAling = Value
End Set
End Property


Public Overrides Function ToString() As String
Return colHeaderText
End Function


End Class

#End Region
---------------------------------------------------
---------------------------------------------------
-------------MultiColumnComboBox class-------------
---------------------------------------------------
---------------------------------------------------

'''''''''''''''''''''''''''''
'''Author : Tahir Ali
'''Last Updated : 21/aug/2005
'''mailto:tahirali_csc@yahoo.com
'''''''''''''''''''''''''''''
Imports System.ComponentModel
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.HtmlControls
Imports System.Drawing.Design
Imports System.Drawing

#Region "multi column combo box control class"
''
''Multi column combo box shows item in multiple columns in tabular form and
''support interllisense on data search.
''
<toolboxdata("<{0}:multicolumncombobox runat="server">"), ToolboxBitmap(GetType(ExtendedWebComboBox.MultiColumnComboBox), "mccbLogo.gif"), _
ParseChildren(True), DefaultProperty("Columns")> _
Public Class MultiColumnComboBox
Inherits System.Web.UI.WebControls.WebControl
Implements INamingContainer

#Region "members variables"

Private txtData As TextBox
Private btnDownArrow As HtmlInputButton
Private rfData As RequiredFieldValidator
Protected WithEvents dgSearch As DataGrid
Private cols As ArrayList
Private ctrlsToHide As ArrayList

Public Delegate Sub OnIntellisenseRowSelect(ByVal sender As LinkButton, ByVal args As SelectedRowEventArgs)
Public Event RowSelectionChanged As OnIntellisenseRowSelect

#End Region

#Region "properties"

#Region "Appearance"

<category("appearance"), description("the="" color="" to="" used="" when="" mouse="" move="" over="" the="" combo="" box="" list="" item")=""> _
Public Property ItemMouseOverColor() As Color
Get
Return Me.ViewState("ItemMouseOverColor")
End Get
Set(ByVal Value As Color)
Me.ViewState("ItemMouseOverColor") = Value
End Set
End Property

<category("appearance"), description("lines="" color="" used="" in="" combobox="" list="" items.")=""> _
Public Property GridLinesColor() As Color
Get
Return Me.ViewState("GridLinesColor")
End Get
Set(ByVal Value As Color)
Me.ViewState("GridLinesColor") = Value
End Set
End Property

<category("appearance"), description("the="" height="" of="" the="" down="" arrow="" button.")=""> _
Public Property DownArrowButtonHeight() As Unit
Get
Return Me.ViewState("DownArrowButtonHeight")
End Get
Set(ByVal Value As Unit)
Me.ViewState("DownArrowButtonHeight") = Value
End Set
End Property

<category("appearance"), description("the="" width="" of="" the="" down="" arrow="" button.")=""> _
Public Property DownArrowButtonWidth() As Unit
Get
Return Me.ViewState("DownArrowButtonWidth")
End Get
Set(ByVal Value As Unit)
Me.ViewState("DownArrowButtonWidth") = Value
End Set
End Property

#End Region

#Region "Validator properties"

<category("validator"), description("the="" tool="" tip="" to="" show="" on="" valiadator.")=""> _
Public Property ValidatorTooltip() As String
Get
Return Me.ViewState("ValidatorTooltip")
End Get
Set(ByVal Value As String)
Me.ViewState("ValidatorTooltip") = Value
End Set
End Property

<category("validator"), description("the="" text="" of="" the="" error="" message.")=""> _
Public Property ValidatorErrorMessage() As String
Get
Return Me.ViewState("ValidatorErrorMessage")
End Get
Set(ByVal Value As String)
Me.ViewState("ValidatorErrorMessage") = Value
End Set
End Property

<category("validator"), description("the="" text="" to="" be="" shown="" for="" the="" label.")=""> _
Public Property ValidatorText() As String
Get
Return Me.ViewState("ValidatorText")
End Get
Set(ByVal Value As String)
Me.ViewState("ValidatorText") = Value
End Set
End Property

<category("validator"), description("how="" the="" validator="" is="" display.")=""> _
Public Property ValidatorDisplayStyle() As ValidatorDisplay
Get
Return Me.ViewState("ValidatorDisplayStyle")
End Get
Set(ByVal Value As ValidatorDisplay)
Me.ViewState("ValidatorDisplayStyle") = Value
End Set
End Property

<category("validator"), description("whether="" the="" validator="" is="" enabled="" or="" not.")=""> _
Public Property ValidatorEnabled() As Boolean
Get
Return Me.ViewState("ValidatorEnabled")
End Get
Set(ByVal Value As Boolean)
Me.ViewState("ValidatorEnabled") = Value
End Set
End Property

#End Region

#Region "non brwosable"

<browsable(false)> _
Public ReadOnly Property TextBox() As TextBox
Get
Return txtData
End Get
End Property

'Classes that Implement IListSource
'DataSet Represents an in-memory cache of data.
'DataTable Represents one table of in-memory data.
<browsable(false)> _
Public Property DataSource() As Object
Get
Return Me.ViewState("DataSource")
End Get
Set(ByVal Value As Object)
Me.ViewState("DataSource") = Value
End Set
End Property

#End Region

#Region "action"

<category("action")> _
Public Property AutoPostBack() As Boolean
Get
Return Me.ViewState("AutoPostBack")
End Get
Set(ByVal Value As Boolean)
Me.ViewState("AutoPostBack") = Value
End Set
End Property

#End Region

#Region "widths"


<category("appearance"), description("the="" height="" of="" the="" combo="" box="" list")=""> _
Public Property ComboBoxListHeight() As Unit
Get
Return Me.ViewState("ComboBoxListHeight")
End Get
Set(ByVal Value As Unit)
Me.ViewState("ComboBoxListHeight") = Value
End Set
End Property

<category("appearance"), description("the="" width="" of="" the="" combo="" box="" list")=""> _
Public Property ComboBoxListWidth() As Unit
Get
Return Me.ViewState("ComboBoxListWidth")
End Get
Set(ByVal Value As Unit)
Me.ViewState("ComboBoxListWidth") = Value
End Set
End Property

<category("appearance"), description("the="" width="" of="" the="" text="" box")=""> _
Public Property TextBoxWidth() As Unit
Get
Return Me.ViewState("TextBoxWidth")
End Get
Set(ByVal Value As Unit)
Me.ViewState("TextBoxWidth") = Value
End Set
End Property

#End Region

#Region "CSS"

<category("css"), description("css="" class="" for="" validator")=""> _
Public Property ValidatorCSS() As String
Get
Return Me.ViewState("ValidatorCSS")
End Get
Set(ByVal Value As String)
Me.ViewState("ValidatorCSS") = Value
End Set
End Property

<category("css"), description("css="" class="" for="" combobox="" list="" header")=""> _
Public Property HeaderCSS() As String
Get
Return Me.ViewState("HeaderCSS")
End Get
Set(ByVal Value As String)
Me.ViewState("HeaderCSS") = Value
End Set
End Property

<category("css"), description("css="" class="" for="" combobox="" list="" items")=""> _
Public Property ItemsCSS() As String
Get
Return Me.ViewState("ItemsCSS")
End Get
Set(ByVal Value As String)
Me.ViewState("ItemsCSS") = Value
End Set
End Property

<category("css"), description("css="" class="" for="" down="" arrow="" button")=""> _
Public Property DownArrowButtonCSS() As String
Get
Return Me.ViewState("DownArrowButtonCSS")
End Get
Set(ByVal Value As String)
Me.ViewState("DownArrowButtonCSS") = Value
End Set
End Property

<category("css"), description("css="" class="" of="" textbox")=""> _
Public Property TextBoxCSS() As String
Get
Return Me.ViewState("TextBoxCSS")
End Get
Set(ByVal Value As String)
Me.ViewState("TextBoxCSS") = Value
End Set
End Property

#End Region

#Region "scrolling"

<category("appearance"), description("whether="" to="" use="" horizontal="" scrolling")=""> _
Public Property HorizontalScrolling() As Boolean
Get
Return Me.ViewState("HorizontalScrolling")
End Get
Set(ByVal Value As Boolean)
Me.ViewState("HorizontalScrolling") = Value
End Set
End Property

<category("appearance"), description("whether="" to="" use="" vertical="" scrolling")=""> _
Public Property VerticalScrolling() As Boolean
Get
Return Me.ViewState("VerticalScrolling")
End Get
Set(ByVal Value As Boolean)
Me.ViewState("VerticalScrolling") = Value
End Set
End Property

#End Region

#Region "collection properties"

<designerserializationvisibility(designerserializationvisibility.content), editor(gettype(controlstohidecollectioneditor),="" _
="" gettype(uitypeeditor)),="" persistencemode(persistencemode.innerproperty),="" category("hide")=""> _
Public ReadOnly Property ControlsToHide() As ArrayList
Get

If ctrlsToHide Is Nothing Then
ctrlsToHide = New ArrayList
End If

Return ctrlsToHide
End Get
End Property

<designerserializationvisibility(designerserializationvisibility.content), editor(gettype(columncollectioneditor),="" _
="" gettype(uitypeeditor)),="" persistencemode(persistencemode.innerproperty),="" category("columns")=""> _
Public ReadOnly Property Columns() As ArrayList
Get

If cols Is Nothing Then
cols = New ArrayList
End If

Return cols
End Get
End Property

#End Region


#End Region

#Region "overrides"

Public Overrides ReadOnly Property Controls() As ControlCollection
Get
EnsureChildControls()
Return MyBase.Controls
End Get
End Property

Public Overrides Sub DataBind()
MyBase.OnDataBinding(EventArgs.Empty)

Controls.Clear()

CreateChildControls()

End Sub


Protected Overrides Sub CreateChildControls()
Dim dtSource As IListSource
Dim keyColIndex As Integer = -1, keyColFound As Boolean = False

dtSource = DataSource

Controls.Clear()

''----Data Text box
txtData = New TextBox
With txtData
.ID = "txtData"
If Not Me.ViewState("TextBoxWidth") Is Nothing Then
.Width = Me.ViewState("TextBoxWidth")
End If
If Not Me.ViewState("TextBoxCSS") Is Nothing Then
.CssClass = Me.ViewState("TextBoxCSS")
End If
End With

''---Down Arrow Button
btnDownArrow = New HtmlInputButton
With btnDownArrow
.ID = "btnDownArrow"
If Not Me.ViewState("DownArrowButtonWidth") Is Nothing Then
.Style("Width") = Me.ViewState("DownArrowButtonWidth").ToString()
End If
If Not Me.ViewState("DownArrowButtonHeight") Is Nothing Then
.Style("height") = Me.ViewState("DownArrowButtonHeight").ToString()
End If
If Not Me.ViewState("DownArrowButtonCSS") Is Nothing Then
.Attributes("class") = Me.ViewState("DownArrowButtonCSS")
End If
End With

''----Required Field Validator
If Not Me.ViewState("ValidatorEnabled") Is Nothing AndAlso _
Me.ViewState("ValidatorEnabled") = True Then
rfData = New RequiredFieldValidator
With rfData
.ControlToValidate = txtData.ID
If Me.ViewState("ValidatorErrorMessage") Is Nothing Then
.ErrorMessage = "Please Enter Data"
Else
.ErrorMessage = Me.ViewState("ValidatorErrorMessage")
End If
If Me.ViewState("ValidatorText") Is Nothing Then
.Text = "*"
Else
.Text = Me.ViewState("ValidatorText")
End If
If Not Me.ViewState("ValidatorDisplayStyle") Is Nothing Then
.Display = Me.ViewState("ValidatorDisplayStyle")
Else
.Display = ValidatorDisplay.None
End If
If Not Me.ViewState("ValidatorCSS") Is Nothing Then
.CssClass = Me.ViewState("ValidatorCSS")
End If
If Not Me.ViewState("ValidatorTooltip") Is Nothing Then
.ToolTip = Me.ViewState("ValidatorTooltip")
End If

End With
End If

''----Data Grid-----
dgSearch = New DataGrid
With dgSearch
.ID = "dgSearch"
.BorderWidth = New Unit(1)
'.GridLines = GridLines.Both
.Width = New Unit("100%")
If Not Me.ViewState("HeaderCSS") Is Nothing Then
.HeaderStyle.CssClass = Me.ViewState("HeaderCSS")
End If
If Not Me.ViewState("ItemsCSS") Is Nothing Then
.ItemStyle.CssClass = Me.ViewState("ItemsCSS")
End If
If Not Me.ViewState("GridLinesColor") Is Nothing Then
.BorderColor = Me.ViewState("GridLinesColor")
Else
.BorderColor = Color.Black
End If
End With


If Not dtSource Is Nothing Then

If Not TypeOf dtSource Is IListSource Then
Throw New Exception("Only DataSet and DataTable are the allowed for data source property")
End If

'If Not (columns Is Nothing AndAlso columns.Count > 0) Then
' Throw New Exception("Specify column styles of multi column combo box")
'End If

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 As Integer = 0

While enmColumns.MoveNext

If keyColCount > 1 Then
Throw New Exception("Only one key column is allowed")
End If
If Not keyColFound Then
keyColIndex += 1
End If

col = CType(enmColumns.Current, Column)
Dim lkColId As String
If Not col.KeyColumn Then
bc = New BoundColumn
bc.Visible = col.Visible
bc.DataField = col.DataField
bc.DataFormatString = col.DataFormatField
bc.ItemStyle.HorizontalAlign = col.HorizontalAlign
bc.HeaderText = col.HeaderText
bc.HeaderStyle.HorizontalAlign = HorizontalAlign.Center
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.Visible = col.Visible
'tc.ItemTemplate = New SearchGridTemplateColumn(ListItemType.Item, col.DataField, lkColId)
'tc.HeaderText = col.HeaderText
''tc.HeaderStyle.Wrap = True
'If col.ColumnWidth.ToString().Length > 0 Then
' tc.HeaderStyle.Width = col.ColumnWidth
'End If
'dgSearch.Columns.Add(tc)

Else

'If Not col.Visible Then
' Throw New Exception("Key Column Should be visible")
'End If

tc = New TemplateColumn
tc.ItemTemplate = New SearchGridTemplateColumn(ListItemType.Item, col.DataField)
tc.HeaderText = col.HeaderText
tc.HeaderStyle.HorizontalAlign = HorizontalAlign.Center
tc.Visible = col.Visible

'tc.HeaderStyle.Wrap = False
If col.ColumnWidth.ToString().Length > 0 Then
tc.HeaderStyle.Width = col.ColumnWidth
End If
dgSearch.Columns.Add(tc)
keyColCount += 1
keyColFound = True
End If

End While

dgSearch.AutoGenerateColumns = False
dgSearch.DataSource = dtSource
dgSearch.DataBind()

End If


Me.Controls.Add(txtData)
Me.Controls.Add(btnDownArrow)
If Not Me.ViewState("ValidatorEnabled") Is Nothing _
AndAlso Me.ViewState("ValidatorEnabled") = True Then
Me.Controls.Add(rfData)
End If
Me.Controls.Add(dgSearch)

Dim divId As String = "div" + Me.ClientID
Dim ctrls_to_hide As String

If Not ctrlsToHide Is Nothing Then
ctrls_to_hide = GetCtrlsToHideIds()
End If


btnDownArrow.Attributes("onclick") = String.Format("onDownArrowBtnClick('{0}','{1}');", divId, ctrls_to_hide)
txtData.Attributes("onkeyup") = "showIntellisense('" + divId + "','" + txtData.ClientID + "','" + dgSearch.ClientID + "','" + ctrls_to_hide + "'," & keyColIndex & ")"
'txtData.Attributes("onkeydown") = "showIntellisense('" + divId + "','" + txtData.ClientID + "','" + dgSearch.ClientID + "')"
txtData.Attributes("onblur") = "document.getElementById('" & divId & "').style.display='none'"
'txtData.Attributes("onblur") = String.Format("onLostFocus('{0}','{1}');", divId, ctrls_to_hide)
'btnDownArrow.Attributes("onmouseleave") = String.Format("onLostFocus('{0}','{1}');", divId, ctrls_to_hide)
'txtData.Attributes("onmouseleave") = String.Format("onLostFocus('{0}','{1}');", divId, ctrls_to_hide)

End Sub

Protected Overrides Sub RenderContents(ByVal writer As System.Web.UI.HtmlTextWriter)

AddAttributesToRender(writer)
writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "0")
writer.AddAttribute(HtmlTextWriterAttribute.Cellspacing, "0")
writer.AddAttribute("onmouseleave", String.Format("onLostFocus('{0}','{1}');", DivId, GetCtrlsToHideIds))
writer.RenderBeginTag(HtmlTextWriterTag.Table)

writer.RenderBeginTag(HtmlTextWriterTag.Tr)
writer.RenderBeginTag(HtmlTextWriterTag.Td)
txtData.RenderControl(writer)
btnDownArrow.RenderControl(writer)
If Not Me.ViewState("ValidatorEnabled") Is Nothing _
AndAlso Me.ViewState("ValidatorEnabled") = True Then
writer.Write(" ")
rfData.RenderControl(writer)
End If
writer.RenderEndTag() ''Td
writer.RenderEndTag() ''Tr

writer.RenderBeginTag(HtmlTextWriterTag.Tr)
writer.RenderBeginTag(HtmlTextWriterTag.Td)

Dim width As Unit
Dim heigth As Unit

If Me.ViewState("ComboBoxListWidth") Is Nothing Then
width = New Unit(200) ''default width of the combo box in pixles
Else
width = Me.ViewState("ComboBoxListWidth")
End If

If Me.ViewState("ComboBoxListHeight") Is Nothing Then
heigth = New Unit(200) ''default width of the combo box in pixles
Else
heigth = Me.ViewState("ComboBoxListHeight")
End If


writer.Write("
") '_
'" onmouseleave=" & String.Format("onLostFocus('{0}','{1}');>", DivId, GetCtrlsToHideIds))

dgSearch.RenderControl(writer)
writer.Write("
")
writer.RenderEndTag() ''Td
writer.RenderEndTag() ''Tr

writer.RenderEndTag() ' Table

End Sub

#End Region

#Region "grid functions"

Private Sub dgSearch_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles dgSearch.ItemDataBound

If e.Item.ItemType <> ListItemType.Header AndAlso e.Item.ItemType <> ListItemType.Footer Then

Dim mouseOverColor As Color
If Me.ViewState("ItemMouseOverColor") Is Nothing Then
mouseOverColor = Color.LightYellow
Else
mouseOverColor = Me.ViewState("ItemMouseOverColor")
End If

e.Item.Attributes.Add("onmouseover", "this.style.backgroundColor='" & ColorTranslator.ToHtml(mouseOverColor) & "'")
e.Item.Attributes.Add("onmousemove", "setData('" & Me.ClientID & "_" & txtData.ClientID + "','" & _
CType(e.Item.FindControl("lkSelect"), LinkButton).Text & "')")
e.Item.Attributes.Add("onmouseout", "this.style.backgroundColor=this.bgColor")
e.Item.Style("cursor") = "hand"

Dim doAutoPostBack As Boolean
If Me.ViewState("AutoPostBack") Is Nothing OrElse Me.ViewState("AutoPostBack") = False Then
doAutoPostBack = False
Else
doAutoPostBack = True
End If

If Not doAutoPostBack Then
'CType(e.Item.FindControl("lkSelect"), LinkButton).Attributes("onclick") = _
'"return onLostFocus('" & DivId & "','" & GetCtrlsToIds() & "')"
''if not doing post back then hide comb box list on item click
e.Item.Attributes("onclick") = "return onLostFocus('" & DivId & _
"','" & GetCtrlsToHideIds() & "')"
End If

End If


End Sub

Private Sub dgSearch_ItemCommand( _
ByVal source As Object, _
ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs _
) Handles dgSearch.ItemCommand

Dim selectedRow As New ArrayList
Dim lkSelect As LinkButton = CType(e.Item.FindControl("lkSelect"), LinkButton)
Dim cellsCount As Integer = dgSearch.Columns.Count
Dim index As Integer
'selectedRow.Add(lkSelect.Text)

For index = 0 To cellsCount - 1
Try
If e.Item.Cells(index).HasControls Then
selectedRow.Add(CType(e.Item.Cells(index).Controls(0), LinkButton).Text)
Else
selectedRow.Add(e.Item.Cells(index).Text)
End If

Catch ex As Exception
Dim arch As New System.IO.StreamWriter("c:\combo.log", False)
arch.WriteLine("Message:" & ex.Message)
arch.WriteLine("StackTrace:" & ex.StackTrace)
arch.WriteLine("cellsCount:" & cellsCount)
arch.WriteLine("e.Item.Cells(" & index & "):" & e.Item.Cells(index).Text)
arch.WriteLine("e.Item.Cells(" & index & ").HasControls:" & e.Item.Cells(index).HasControls)


arch.Flush()
arch.Close()
End Try

Next

RaiseEvent RowSelectionChanged(CType(e.Item.FindControl("lkSelect"), LinkButton), New SelectedRowEventArgs(selectedRow))

End Sub

#End Region

#Region "helper functions"

Private ReadOnly Property DivId() As String
Get
Return "div" & Me.ClientID
End Get
End Property

Private ReadOnly Property DivCSS() As String
Get
Dim css As New System.Text.StringBuilder
Dim xScrolling As String, yScrolling

css.Append("BORDER-RIGHT: black 1px solid;")
css.Append("BORDER-TOP: black 1px solid;")
css.Append("BORDER-BOTTOM: black 1px solid;")
css.Append("BORDER-LEFT: black 1px solid;")
'css.Append("SCROLLBAR-FACE-COLOR: #ccccff;")
'css.Append("SCROLLBAR-HIGHLIGHT-COLOR: white;")
'css.Append("SCROLLBAR-SHADOW-COLOR: white;")
'css.Append("SCROLLBAR-3DLIGHT-COLOR: blue;")
'css.Append("SCROLLBAR-ARROW-COLOR: blue;")
'css.Append("SCROLLBAR-TRACK-COLOR: #eef7ff;")
'css.Append("BORDER-RIGHT: black 1px solid;")
'css.Append("SCROLLBAR-DARKSHADOW-COLOR: black;")

If Me.ViewState("HorizontalScrolling") Is Nothing OrElse _
Not Me.ViewState("HorizontalScrolling") Then
xScrolling = "none"
Else
xScrolling = "auto"
End If

If Me.ViewState("VerticalScrolling") Is Nothing OrElse _
Not Me.ViewState("VerticalScrolling") Then
yScrolling = "none"
Else
yScrolling = "auto"
End If

css.AppendFormat("overflow-x:{0};", xScrolling)
css.AppendFormat("overflow-y:{0};", yScrolling)
Return css.ToString
End Get
End Property

Public Function GetCtrlsToHideIds() As String

Dim ctrls_to_hide As String

If Not ctrlsToHide Is Nothing Then
Dim enmCtrlsToHide As IEnumerator = ctrlsToHide.GetEnumerator

enmCtrlsToHide.MoveNext()
ctrls_to_hide = CType(enmCtrlsToHide.Current, HiddenControl).ControlId
While enmCtrlsToHide.MoveNext()
ctrls_to_hide += "-" & CType(enmCtrlsToHide.Current, HiddenControl).ControlId
End While
End If

Return ctrls_to_hide

End Function

#End Region


End Class

#End Region

#Region "template column class"

Friend Class SearchGridTemplateColumn
Implements ITemplate

Private templateType As ListItemType ''either it header template,item template or footer template.
Private columnName As String
Private ctrlId As String = "lkSelect"

Public Sub New(ByVal type As ListItemType, ByVal ColName As String)
Me.templateType = type
Me.columnName = ColName
End Sub

Public Sub New(ByVal type As ListItemType, ByVal ColName As String, ByVal id As String)
Me.New(type, ColName)
Me.ctrlId = id
End Sub

Protected Sub DataBind(ByVal sender As Object, ByVal e As EventArgs)
Dim lk As LinkButton
Dim colValue As Object
lk = CType(sender, LinkButton)
lk.CausesValidation = False

Dim dgi As DataGridItem
dgi = CType(lk.NamingContainer, DataGridItem)

colValue = CType(dgi.DataItem, DataRowView).Row.Item(Me.columnName)

If Convert.IsDBNull(colValue) OrElse colValue.ToString().Trim().Length = 0 Then
lk.Text = String.Empty
Else
lk.Text = colValue
End If

'lk.Text = CType(CType(dgi.DataItem, DataRowView).Row.Item(Me.columnName), String)
End Sub


Public Sub InstantiateIn(ByVal container As System.Web.UI.Control) Implements System.Web.UI.ITemplate.InstantiateIn
Dim lk As LinkButton

Select Case 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)

End Select

End Sub

End Class

#End Region

#Region "Row selection event argument class"

Public Class SelectedRowEventArgs
Inherits EventArgs

Private selectedRow As ArrayList

Public Sub New(ByVal row As ArrayList)
Me.selectedRow = row
End Sub

Public ReadOnly Property Cells() As ArrayList
Get
Return selectedRow
End Get
End Property

End Class

#End Region



RonSolo

QuestionCodebehind in vb.net Pin
rawvette31-Aug-06 6:36
rawvette31-Aug-06 6:36 
GeneralCombo box not responding when I type text in Pin
rawvette28-Aug-06 9:25
rawvette28-Aug-06 9:25 
Question.Net2005 Pin
sfsaaaa14-Jul-06 7:57
sfsaaaa14-Jul-06 7:57 
AnswerRe: .Net2005 [modified] Pin
Goran Bacvarovski9-Aug-06 16:59
Goran Bacvarovski9-Aug-06 16:59 
GeneralRe: .Net2005 Pin
dsmportal16-Apr-07 4:41
dsmportal16-Apr-07 4:41 
GeneralData-binding speed too slow Pin
sourcevbdotnet28-Jun-06 18:31
sourcevbdotnet28-Jun-06 18:31 
GeneralRe: Data-binding speed too slow Pin
Tahir 1116-Jul-06 19:20
Tahir 1116-Jul-06 19:20 
GeneralRe: Data-binding speed too slow Pin
sourcevbdotnet7-Jul-06 5:25
sourcevbdotnet7-Jul-06 5:25 
QuestionRe: Data-binding speed too slow Pin
cyeung6-Nov-06 19:39
cyeung6-Nov-06 19:39 
QuestionGrid View Pin
mbkasi15-May-06 0:11
mbkasi15-May-06 0:11 
AnswerRe: Grid View Pin
Tahir 1114-Jun-06 18:12
Tahir 1114-Jun-06 18:12 
QuestionHow to get its Selected Index Pin
Sonal Bansal9-May-06 2:46
Sonal Bansal9-May-06 2:46 
AnswerRe: How to get its Selected Index Pin
Tahir 11111-May-06 18:12
Tahir 11111-May-06 18:12 
QuestionHow to make its TextBox as ReadOnly Pin
Sonal Bansal9-May-06 2:25
Sonal Bansal9-May-06 2:25 
GeneralError Rendering control - not show control! Pin
caspersvn9-Apr-06 17:57
caspersvn9-Apr-06 17:57 
GeneralRe: Error Rendering control - not show control! Pin
Tahir 11112-Apr-06 19:18
Tahir 11112-Apr-06 19:18 
GeneralRe: Error Rendering control - not show control! Pin
Wayne Ligon27-Jul-06 8:39
Wayne Ligon27-Jul-06 8:39 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.