This is a migrated thread and some comments may be shown as answers.

[Solved] Adding columns in page_init but getting Multiple Controls With The Same ID

1 Answer 303 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Nick
Top achievements
Rank 1
Nick asked on 09 Jun 2009, 10:47 AM
Hi,


I'm using RadControls for ASP.NET AJAX Q1 2009


I have a radgrid using NeedDataSource to bind to a dynamicallyt created datasource, depending on columns the user has selected. The grid is created in page_init as recommended to me.

I dynamically create the grid columns myself. One fo these columns is a template column containing a radeditor. I was advised to create columns, especially templated columns, in page_init. When I do this though, I get

Multiple controls with the same ID 'FilterTextBox_tblT1Devices.Name' were found. FindControl requires that controls have unique IDs.

If I create the columns in page load I don't get this message but my template column will disappear after postback as expected, because it's viewstate is not saved.

Another issue is my dynamically created dropdown columns are completely blank no matter what way I configure them. I have had problems with them for days. I'm hoping their problem might be related.

Please advise.


Relevant code :

 
    Protected Sub Page_Init(ByVal sender As ObjectByVal e As System.EventArgs) Handles Me.Init  
 
 
        ' If loading for the first time...  
 
        'Create the Grid  
        Dim grid As New RadGrid()  
        grid.ID = "gridServers" 
        grid.Skin = "Default" 
        grid.PageSize = 100  
        grid.AllowPaging = True 
        grid.AllowFilteringByColumn = True 
        grid.AllowSorting = True 
        grid.ShowGroupPanel = True 
        grid.PagerStyle.Mode = GridPagerMode.NextPrevAndNumeric  
        grid.AutoGenerateColumns = False 
        grid.CssClass = "gridServers" 
 
        AddHandler grid.ColumnCreated, AddressOf gridServers_ColumnCreated  
        AddHandler grid.NeedDataSource, AddressOf gridServers_NeedDataSource  
 
        gridServersHere.Controls.Add(grid)  
 
 
        ' Initialize the page  
        Initialize()          
        rptColumnSelector.DataSource = Session("showColumns")  
        rptColumnSelector.DataBind()  
        PrepareGridColumns()  
 
    End Sub 
 
 
    Protected Sub Page_Load(ByVal sender As ObjectByVal e As System.EventArgs) Handles Me.Load  
 
        ' If loading for the first time...  
        If Not Page.IsPostBack Then 
 
            ' Initialize the page  
            'Initialize()  
            'PrepareGridColumns()  
            rptColumnSelector.DataSource = Session("showColumns")  
            rptColumnSelector.DataBind()  
            'gridServers.DataBind()              
        End If 
    End Sub 
 
 
    Protected Function getDataString() As String 
 
        Dim columnList As Data.DataTable = Session("showColumns")  
        Dim selectStr As String = "" 
        Dim joinstr As String = "" 
        Dim column As Data.DataRow  
        Dim i = 0  
 
        selectStr = "select tblT1Devices.DeviceID as [Device ID], tblT2Configuration.EnvironmentID as [ThisID] " 
 
        'build a comma-delimited list of columns that will make up the SQL Query.  
        'Dont put a comma after the last one.  
        If columnList Is Nothing Then 
            Initialize()  
            columnList = Session("showColumns")  
        End If 
 
        For Each column In columnList.Rows  
            ' Process only the checked columns.  
            If column("Checked") = True Then 
 
                selectStr = selectStr + ", " + column("FullName") + " as [" + column("FullName") + "]" 
 
 
                ' Commented out at the moment. We are doing the simple version above.  
 
 
 
                '                Select Case column("LookupTable")  
 
                ' If this is a straight forward field :  
                '                   Case ""  
                '              selectStr = selectStr + ", " + column("FullName") + " as [" + column("FullName") + "]"  
 
 
                'Otherwise is must be a lookup ID :  
                '                 Case Else  
                '            selectStr = selectStr + ", "  
                '           selectStr = selectStr + column("TABLE_NAME") + column("COLUMN_NAME") + "." + column("LookupValue") + " as [" + column("FullName") + "]"  
 
                'Join Str is a string we're contructing of SQL Joins, while we'rein the same loop. This will be tagged on the end of  
                'selectstr after this loop.  
 
                '          joinstr = joinstr + " left join " + column("LookupTable") + " as " + column("TABLE_NAME") + column("COLUMN_NAME")  
                '         joinstr = joinstr + " on " + column("TABLE_NAME") + column("COLUMN_NAME") + "." + column("LookupID") + " = " + column("FullName")  
                '        End Select  
 
 
            End If 
            'If i < columnCount Then selectStr = selectStr + ","  
            'i += 1  
        Next 
   
        selectStr = selectStr + " from tblT1Devices left join tblt2configuration on tblT2configuration.deviceID = tblT1Devices.deviceid" 
        selectStr = selectStr + " left join tblt3_MV_Configuration on tblT3_MV_Configuration.deviceID = tblT1Devices.deviceid" 
        'selectStr = selectStr + joinstr  
 
        Return selectStr  
 
    End Function 
 
 
    Protected Sub Initialize()  
 
        Dim column As DataRow  
 
        Dim ColumnList As Data.DataTable = CreateColumnListDataTable()  
 
        'A list of Column Names we want to show by default on the Grid:  
        Dim SelectedColumns As String() = {"tblT1Devices.Name""tblT1Devices.Domain"}  
        Dim selectColumn As String 
 
        'Get all available columns from the SP  
        Dim ConnString As String = ConfigurationManager.ConnectionStrings("WPG_ADBConnectionString").ConnectionString  
        Dim conn As SqlConnection = New SqlConnection(ConnString)  
        Dim adapter As SqlDataAdapter = New SqlDataAdapter  
        adapter.SelectCommand = New SqlCommand("exec sp_web_Search_GetAvailableColumns", conn)  
 
        Dim table1 As New DataTable  
        conn.Open()  
        Try 
            adapter.Fill(table1)  
        Finally 
            conn.Close()  
        End Try 
 
 
        'We add a column here that will hold whether the column is checked on the GUI  
        'Then Cycle through all the checkboxes and check those that match the default list above   
        Dim myDataColumn As DataColumn  
 
        myDataColumn = New DataColumn()  
        myDataColumn.DataType = Type.GetType("System.Boolean")  
        myDataColumn.ColumnName = "Checked" 
        table1.Columns.Add(myDataColumn)  
 
        For Each column In table1.Rows  
            column("Checked") = False ' Check them all to false by default.  
            For Each selectColumn In SelectedColumns  
                If selectColumn = column("FullName"Then 
                    column("Checked") = True 'check them to true if in the list above.  
                End If 
            Next 
        Next 
 
        'Set the FullName Column as the PrimaryKey  
        'Dim Key() As DataColumn  
        'Key(0) = table1.Columns("FullName")  
        'Key(0) = table1.Columns.Item("FullName")  
        'table1.PrimaryKey = Key  
 
 
        'For Each item In rpt.Items  
        '        chk = item.FindControl("chkColumn")  
        'chkColumn = chk.ToolTip.Split("-")  
        'For Each selectColumn In SelectedColumns  
        '        If selectColumn = chkColumn(0) Then  
        '        chk.Checked = "true"  
        'End If  
        'Next  
        'Next  
 
        'update the session variable of checked columns  
        Session("showColumns") = table1  
 
    End Sub 
 
    Protected Sub gridServers_ColumnCreated(ByVal sender As ObjectByVal e As Telerik.Web.UI.GridColumnCreatedEventArgs)  
 
        Dim ColumnList As DataTable = Session("showColumns")  
        Dim myColumn As DataRow  
 
 
        'Go through all columns and perform specific tasks depending on row types.  
        For Each myColumn In ColumnList.Rows  
 
            'For any columns in the grid that match our datatable of extra column data ... :  
            'If e.Column.UniqueName = myColumn("FullName") Then  
            '            e.Column.HeaderText = myColumn("FriendlyColumnName")  
            'e.Column.HeaderTooltip = e.Column.HeaderTooltip + " - " + myColumn("FullName") & " - " & myColumn("Description")  
 
            'Detect column types and set to readonly if the column is readonly.  
            'Select Case e.Column.ColumnType  
 
            '    Case "GridBoundColumn"  
            'Dim boundColumn As GridBoundColumn = CType(e.Column, GridColumn)  
            'boundColumn.ReadOnly = Boolean.Parse(myColumn("Readonly"))  
            'If Not boundColumn.ReadOnly Then e.Column.HeaderStyle.ForeColor = System.Drawing.ColorTranslator.FromHtml("#0269ff")  
 
            'Case "GridCheckBoxColumn"  
            'Dim boundColumn As GridCheckBoxColumn = CType(e.Column, GridColumn)  
            'boundColumn.ReadOnly = Boolean.Parse(myColumn("Readonly"))  
            'If Not boundColumn.ReadOnly Then e.Column.HeaderStyle.ForeColor = System.Drawing.ColorTranslator.FromHtml("#0269ff")  
 
            'End Select  
 
 
            'Check for Lookup tables and change the column type to dropdowns for editing purposes  
            ' Note that the grid doesnt autodetect this osrt of thing (like checkboxes) so we have to tell it to.  
            ' Otherwise it will just use GridBoundColumn  
 
            'If a lookup table is specified  
            'If myColumn("Lookuptable") <> "" Then  
            ' e.Column.co()  
            'End If  
 
 
            'End If  
 
 
            'If the column is the DeviceID, make sure this is readonly as it is the primary key.  
            If e.Column.UniqueName = "Device ID" Then 
                Dim boundColumn As GridBoundColumn = CType(e.Column, GridBoundColumn)  
                boundColumn.ReadOnly = True 
            End If 
        Next 
 
 
 
        ' For edit column  
        If e.Column.ColumnType = "Telerik.Web.UI.GridEditCommandColumn" Then 
 
        End If 
 
 
 
 
    End Sub 
 
 
    Protected Sub gridServers_UpdateCommand(ByVal source As ObjectByVal e As Telerik.Web.UI.GridCommandEventArgs)  
 
        Dim ColumnList As Data.DataTable = Session("showColumns")  
        Dim columnName As Data.DataRow  
 
 
        Dim sqlstring = "" 
        Dim w = "Telerik.Web.UI.GridEditFormItem" 
 
        'Get the GridEditableItem of the RadGrid  
        Dim editedItem As GridEditableItem = TryCast(e.Item, GridEditableItem)  
 
        'Get the primary key value using the DataKeyValue.  
        Dim DeviceID As String = editedItem.OwnerTableView.DataKeyValues(editedItem.ItemIndex)("Device ID").ToString()  
 
        Dim sql As SqlDataSource = New SqlDataSource  
        sql.ConnectionString = ConfigurationManager.ConnectionStrings("WPG_ADBConnectionString").ConnectionString  
 
        'have to put at least one update statement (deviceid = deviceid) so anything added after has a comma before it  
        sqlstring = "Update tblT3_MV_Configuration set DeviceID = " & DeviceID & " " 
 
 
        For Each columnName In ColumnList.Rows  
 
            'only if column is readonly and checked.....  
            If columnName("ReadOnly") <> "true" And columnName("Checked"Then 
 
                Dim name As String = editedItem(columnName(5)).controls(0).GetType().ToString()  
 
                Select Case editedItem(columnName("Fullname")).controls(0).GetType().ToString()  
 
                    Case "System.Web.UI.WebControls.TextBox" 
                        sqlstring = sqlstring & ", " & columnName(0) & " = '" & (TryCast(editedItem(columnName("Fullname")).Controls(0), TextBox)).Text & "', " 
 
                    Case "System.Web.UI.WebControls.CheckBox" 
                        sqlstring = sqlstring & ", " & columnName("FullName") & " = '" & (TryCast(editedItem(columnName("Fullname")).Controls(0), CheckBox)).Checked.ToString & "', " 
 
                    Case "System.Web.UI.WebControls.dropdownlist" 
                        sqlstring = sqlstring & ", " & columnName("FullName") & " = '" & (TryCast(editedItem(columnName("Fullname")).Controls(0), DropDownList)).SelectedItem.Value & "', " 
 
                        'might use this later :  
                        'telerik.Web.UI.RadDateInput  
 
                End Select 
            End If 
        Next 
 
        sqlstring = sqlstring & " where DeviceID = " & DeviceID  
 
        'Will do update here......  
    End Sub 
 
 
    Protected Sub gridServers_NeedDataSource(ByVal source As ObjectByVal e As Telerik.Web.UI.GridNeedDataSourceEventArgs)  
 
        'Set up grid columns acording to our selected column list  
        'Not any more, do this in Page_init  
        'PrepareGridColumns()  
 
        Dim gridServers As RadGrid = source  
        Dim value() As String = {"Device ID"}  
        gridServers.DataSource = GetDataTable()  
        gridServers.MasterTableView.DataKeyNames = value  
 
    End Sub 
 
 
    Public Function GetDataTable() As DataTable  
        Dim ConnString As String = ConfigurationManager.ConnectionStrings("WPG_ADBConnectionString").ConnectionString  
        Dim conn As SqlConnection = New SqlConnection(ConnString)  
        Dim adapter As SqlDataAdapter = New SqlDataAdapter  
        adapter.SelectCommand = New SqlCommand(getDataString(), conn)  
        Dim table1 As New DataTable  
        conn.Open()  
        Try 
            adapter.Fill(table1)  
        Finally 
            conn.Close()  
        End Try 
        Return table1  
    End Function 
 
 
 
    Public Sub PrepareGridColumns()  
 
 
        'This function will generate the columns for the Grid by looping through the checkbox datatable  
        ' Instead of autogenerating, this way I can handpick and identify the dropdown\lookup columns  
 
        Dim gridServers As RadGrid = gridServersHere.FindControl("gridServers")  
        Dim column As DataRow  
        Dim columnList As DataTable = Session("showColumns")  
        Dim AnyColumnsAreEditable As Boolean = False 
 
        'Clear Columns  
        gridServers.Columns.Clear()  
 
        Dim editcol As New GridEditCommandColumn()  
        gridServers.MasterTableView.Columns.Add(editcol)  
 
 
        Dim sql1 As New SqlDataSource  
        sql1.ID = "sqlEnv" 
        sql1.ConnectionString = ConfigurationManager.ConnectionStrings("WPG_ADBConnectionString").ConnectionString  
        sql1.SelectCommand = "select * from tblT3Environments" 
 
        Dim dd As New GridDropDownColumn  
 
        gridServers.MasterTableView.Columns.Add(dd)  
        dd.ListValueField = "EnvironmentID" 
        dd.ListTextField = "Environment" 
        dd.DataSourceID = sql1.ID  
        dd.HeaderText = "Scooby" 
        dd.DataField = "ThisID" 
 
        For Each column In columnList.Rows  
            If column("Checked"Then 
 
                If column("LookupTable") <> "" Then 
 
                    Dim sql As New SqlDataSource  
                    sql.ID = "sql" & column("Table_Name") & column("column_Name")  
                    sql.ConnectionString = ConfigurationManager.ConnectionStrings("WPG_ADBConnectionString").ConnectionString  
                    sql.SelectCommand = "select " & column("LookupID") & ", " & column("LookupValue") & " from " & column("LookupTable")  
 
                    Dim dropdowncol As New GridDropDownColumn  
 
                    gridServers.MasterTableView.Columns.Add(dropdowncol)  
                    dropdowncol.ListValueField = column("LookupID")  
                    dropdowncol.ListTextField = column("LookupValue")  
                    dropdowncol.DataSourceID = sql.ID  
                    dropdowncol.HeaderText = column("FriendlyColumnName")  
                    dropdowncol.DataField = column("FullName")  
                    dropdowncol.UniqueName = column("FullName")  
                    dropdowncol.ReadOnly = Boolean.Parse(column("Readonly"))  
                    dropdowncol.SortExpression = column("FullName")  
                    dropdowncol.Groupable = True 
                    dropdowncol.GroupByExpression = column("FullName") + " Group By " + column("FullName")  
 
                Else 
 
                    If column("DATA_TYPE") = "varchar" Or column("DATA_TYPE") = "nvarchar" Then 
 
                        Dim boundcol As New GridBoundColumn()  
                        gridServers.MasterTableView.Columns.Add(boundcol)  
                        boundcol.UniqueName = column("FullName")  
                        boundcol.HeaderText = column("FriendlyColumnName")  
                        boundcol.DataField = column("FullName")  
                        boundcol.HeaderTooltip = boundcol.HeaderTooltip.ToString() + " - " + column("FullName") & " - " & column("Description")  
                        boundcol.ReadOnly = Boolean.Parse(column("Readonly"))  
                        boundcol.SortExpression = column("FullName")  
                        boundcol.Groupable = True 
                        boundcol.GroupByExpression = column("FullName") + " Group By " + column("FullName")  
 
 
 
 
                    ElseIf column("DATA_TYPE") = "datetime" Then 
 
                        Dim datecol As New GridDateTimeColumn()  
                        gridServers.MasterTableView.Columns.Add(datecol)  
                        datecol.UniqueName = column("FullName")  
                        datecol.HeaderText = column("FriendlyColumnName")  
                        datecol.DataField = column("FullName")  
                        datecol.HeaderTooltip = datecol.HeaderTooltip.ToString() + " - " + column("FullName") & " - " & column("Description")  
                        datecol.ReadOnly = Boolean.Parse(column("Readonly"))  
                        datecol.PickerType = GridDateTimeColumnPickerType.DateTimePicker  
 
 
                    ElseIf column("DATA_TYPE") = "int" Or column("DATA_TYPE") = "bigint" Then 
 
                        Dim intcol As New GridNumericColumn()  
                        gridServers.MasterTableView.Columns.Add(intcol)  
                        intcol.UniqueName = column("FullName")  
                        intcol.HeaderText = column("FriendlyColumnName")  
                        intcol.DataField = column("FullName")  
                        intcol.HeaderTooltip = intcol.HeaderTooltip.ToString() + " - " + column("FullName") & " - " & column("Description")  
                        intcol.ReadOnly = Boolean.Parse(column("Readonly"))  
 
 
                    ElseIf column("DATA_TYPE") = "text" Then 
 
                        Dim tempcol As New GridTemplateColumn()  
 
                        'The class for this template can be found at the bottom of this code-behind  
                        tempcol.EditItemTemplate = New MyEditBoxTemplate(column("FullName"))  
 
                        tempcol.UniqueName = column("FullName")  
                        tempcol.HeaderText = column("FriendlyColumnName")  
                        tempcol.DataField = column("FullName")  
                        tempcol.HeaderTooltip = tempcol.HeaderTooltip.ToString() + " - " + column("FullName") & " - " & column("Description")  
                        tempcol.ReadOnly = Boolean.Parse(column("Readonly"))  
                        gridServers.MasterTableView.Columns.Add(tempcol)  
 
                    ElseIf column("DATA_TYPE") = "bit" Then 
 
                        Dim Checkcol As New GridCheckBoxColumn()  
                        gridServers.MasterTableView.Columns.Add(Checkcol)  
                        Checkcol.UniqueName = column("FullName")  
                        Checkcol.HeaderText = column("FriendlyColumnName")  
                        Checkcol.DataField = column("FullName")  
                        Checkcol.HeaderTooltip = Checkcol.HeaderTooltip.ToString() + " - " + column("FullName") & " - " & column("Description")  
 
                        Checkcol.ReadOnly = Boolean.Parse(column("Readonly"))  
 
                    Else 
                        Dim boundcol As New GridBoundColumn()  
                        gridServers.MasterTableView.Columns.Add(boundcol)  
                        boundcol.UniqueName = column("FullName")  
                        boundcol.HeaderText = column("FriendlyColumnName")  
                        boundcol.DataField = column("FullName")  
                        boundcol.HeaderStyle.ForeColor = Drawing.Color.Red  
                        boundcol.HeaderTooltip = boundcol.HeaderTooltip.ToString() + " - " + column("FullName") & " - " & column("Description")  
                        boundcol.ReadOnly = Boolean.Parse(column("Readonly"))  
 
                    End If 
 
                End If 
 
            End If 
        Next 
 
 
    End Sub 
    Private Class MyEditBoxTemplate  
        Implements ITemplate  
 
        Protected EditBox As RadEditor  
 
        Private colname As String 
 
        Public Sub New(ByVal cName As String)  
            MyBase.New()  
            colname = cName  
        End Sub 
 
        Public Sub InstantiateIn(ByVal container As System.Web.UI.Control) Implements ITemplate.InstantiateIn  
 
            EditBox = New RadEditor  
            EditBox.ID = "editBox" 
 
            'Format edit Box  
            EditBox.Width = "500" 
            EditBox.Width = "300" 
 
            Dim myTools() As String = {"ToggleScreenMode""Bold""Italic""Underline""Fontsize""Fontname""Cut""Copy""Paste", _  
                                       "Undo""Redo""Indent""Outdent"}  
            Dim toolname As String 
            Dim Main As New EditorToolGroup()  
            For Each toolname In myTools  
                Dim tool As New EditorTool(toolname)  
                tool.Type = EditorToolType.Button  
                Main.Tools.Add(tool)  
            Next 
 
            EditBox.Tools.Add(Main)  
 
            AddHandler EditBox.DataBinding, AddressOf Me.EditBox_DataBinding  
            container.Controls.Add(EditBox)  
        End Sub 
 
        Private Sub EditBox_DataBinding(ByVal sender As ObjectByVal e As EventArgs)  
            Dim eBox As RadEditor = CType(sender, RadEditor)  
            Dim container As GridEditFormItem = CType(eBox.NamingContainer, GridEditFormItem)  
            'eBox.Content = CType(container.DataItem, DataRowView)(colname).ToString()  
            eBox.Content = "<b>Server Notes</b><br/><br/>Previous server notage may not be modified. Any notes written and saved here will be appended." 
        End Sub 
 
    End Class 
 
End Class 
 

1 Answer, 1 is accepted

Sort by
0
Tsvetoslav
Telerik team
answered on 11 Jun 2009, 11:02 AM
Hello Nick,

From the code snippets it is difficult to say what exactly might be throwing this exception. However, I'd like to draw you attention to a couple of points:

1. Please, review the following help article on the programmatic creation of the gird in Page_Init : http://www.telerik.com/help/aspnet-ajax/grdprogrammaticcreation.html
and the following couple of online examples on Simple Data Binding (http://demos.telerik.com/aspnet-ajax/grid/examples/programming/simplebinding/defaultcs.aspx) and Advanced Data Binding (http://demos.telerik.com/aspnet-ajax/grid/examples/programming/needdatasource/defaultcs.aspx)

2. You should not be binding the grid neither in the Page_Init event nor in the Page_Load event. The NeedDataSource handler is completely sufficient for the grid to bind properly.

Please, give this suggestions a try and see if they help.


Kind regards,
Tsvetoslav
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Check out the tips for optimizing your support resource searches.
Tags
Grid
Asked by
Nick
Top achievements
Rank 1
Answers by
Tsvetoslav
Telerik team
Share this question
or