Выпадающий список SelectedIndexChanged не запускается в настраиваемом серверном элементе управления Gridview

Я создаю настраиваемый серверный элемент управления ASP.Net gridview (не пользовательский элемент управления) с помощью настраиваемого пейджера. Пользовательский пейджер содержит динамически добавляемый раскрывающийся список, который изменяет размер страницы gridview (элементов на странице). Выпадающий список добавлен в метод RenderChildren, который я переопределяю в коде серверного элемента управления.

Я в основном клонирую строку пейджера по умолчанию и добавляю раскрывающийся список в строку, затем добавляю клонированную строку пейджера в gridview и уничтожаю оригинал.

Проблема в том, что даже если для свойства autopostback выпадающего списка установлено значение true и я добавляю для него обработчик событий, я не могу заставить событие срабатывать при изменении selectedindex. Я пробовал несколько разных подходов, но безуспешно.

Я считаю, что проблема в том, что выпадающий список еще не был отрисован к моменту изменения selectedindex на вызывающей странице. Но я недостаточно знаю о серверных элементах управления и жизненном цикле страницы, чтобы понять, как это решить.

Вот сокращенная версия кода:

Public Class CustomGridView
    Inherits System.Web.UI.WebControls.GridView
    Implements IPostBackEventHandler

    Protected WithEvents mctlDropdownListPageSize As New DropDownList
    Public Event PageSizeChanged(ByVal sender As Object, ByVal e As EventArgs)

    Protected Sub dropdownListPageSize_Click(ByVal sender As Object, ByVal e As EventArgs)
        RaiseEvent PageSizeChanged(Me.mctlDropdownListPageSize, e)
    End Sub

    'This sets up paging using the pageddatasource
    Protected Overrides Sub InitializePager(row As GridViewRow, columnSpan As Integer, pagedDataSource As PagedDataSource)
        pagedDataSource.AllowPaging = True
        pagedDataSource.AllowCustomPaging = True
        pagedDataSource.VirtualCount = TotalRows
        pagedDataSource.CurrentPageIndex = CurrentPageIndex
        Me.PageIndex = CurrentPageIndex
        MyBase.InitializePager(row, columnSpan, pagedDataSource)
    End Sub

    Protected Overrides Sub RenderChildren(writer As HtmlTextWriter)
        Try
            If Me.Controls.Count = 0 Then
                ' nothing to render, use default
                MyBase.RenderChildren(writer)
                Return
            End If

            ' select the header row in the grid
            Dim gridViewTable As WebControl = DirectCast(Me.Controls(0), WebControl) ' the table

            ' the table->row(0) if no top paging, otherwise row(1)
            Dim pagerRow As GridViewRow = gridViewTable.Controls(0)

            'Get the pager cell -- we want only one cell containing all the elements
            Dim pagerContainerCell As TableCell = pagerRow.Cells(0)

            'Create the new table which will contain the title, results summary and pager
            Dim newPagerTable As New Table
            newPagerTable.CellPadding = 0
            newPagerTable.CellSpacing = 0
            newPagerTable.CssClass = "section_headers gridpagertable"

            'Create a table row to contain the new cells
            Dim newPagerRow As New TableRow
            newPagerRow.CssClass = "pagerrow"

            'Create 2 cells to hold the new controls + pager
            Dim resultsCell As New TableCell
            resultsCell.CssClass = "results"
            Dim pagerCell As New TableCell
            pagerCell.CssClass = "pager"

            If Me.AllowPaging Then
                'Add the pagesize dropdown and results summary text
                'Create the results label 
                Dim mctlResultsLabelText As New LiteralControl
                mctlResultsLabelText.Text = "<span>Results per page </span>"

                'Create the pagesize dropdown container div
                Dim mctlResultsDropdownListContainerDiv As New HtmlControls.HtmlGenericControl("div")
                mctlResultsDropdownListContainerDiv.Attributes("class") = "dropdown_select"

                Dim mctlResultsDropdownListLabel As New HtmlControls.HtmlGenericControl("label")

                'Create the pagesize dropdownlist
                mctlDropdownListPageSize.ID = "dropDownListPageSize"
                mctlDropdownListPageSize.Items.Add(New ListItem("100", "100"))
                mctlDropdownListPageSize.Items.Add(New ListItem("200", "200"))
                mctlDropdownListPageSize.Items.Add(New ListItem("300", "300"))
                mctlDropdownListPageSize.AutoPostBack = True
                mctlDropdownListPageSize.EnableViewState = True
                AddHandler mctlDropdownListPageSize.SelectedIndexChanged, AddressOf Me.dropdownListPageSize_Click

                'Add the dropdown tot he dropdown container div
                mctlResultsDropdownListLabel.Controls.Add(mctlDropdownListPageSize)
                mctlResultsDropdownListContainerDiv.Controls.Add(mctlResultsDropdownListLabel)

                'Add the results drpdown label
                resultsCell.Controls.Add(mctlResultsLabelText)
                'Add the pagesize dropdown
                resultsCell.Controls.Add(mctlResultsDropdownListContainerDiv)
                'Add the cell to the row
                newPagerRow.Controls.Add(resultsCell)
            End If

            'Add the pager control and action icons
            Dim mctlPagerContainerDiv As New HtmlControls.HtmlGenericControl("div")
            mctlPagerContainerDiv.Attributes.Add("class", "pagination")


            'Add the div to the pager cell
            pagerCell.Controls.Add(mctlPagerContainerDiv)

            If Me.AllowPaging Then
                'Get the existing pager container table with the pager buttons
                Dim tblPager As Table
                tblPager = pagerContainerCell.Controls(0)
                tblPager.CellPadding = 0
                'Add the pager to the cell
                pagerCell.Controls.Add(tblPager)
            End If

            'Add the cell to the row
            newPagerRow.Controls.Add(pagerCell)

            'Add the row to the table
            newPagerTable.Controls.Add(newPagerRow)
            'Render the new pager row (table+row+3 new cells with controls)
            newPagerTable.RenderControl(writer)

            If Me.AllowPaging Then
                ' remove the original (default) pager row, otherwise we have two
                gridViewTable.Controls.RemoveAt(0)
            End If

            'Render the gridview
            gridViewTable.RenderControl(writer)

        Catch ex As Exception
            ControlErrorHandler(ex, "RenderChildren")
        End Try

    End Sub

    Private Sub ControlErrorHandler(ByVal ex As Exception, ByVal methodName As String)
        Throw New ApplicationException(Me.GetType().ToString & "." & methodName & " failed due to the inner error - " & ex.Message, ex)
    End Sub

    <Description("The current page index of the gridview."), DefaultValue(""), Themeable(False), Category("Appearance")> _
    Public Property CurrentPageIndex() As Integer
        Get
            If Not ViewState(VSKeyCurrPageIndex) Is Nothing Then
                Return Integer.Parse(ViewState(VSKeyCurrPageIndex))
            Else
                Return 0
            End If
        End Get
        Set(value As Integer)
            ViewState(VSKeyCurrPageIndex) = value
        End Set
    End Property


End Class

На вызывающей странице есть следующее:

Private Sub gridViewResults_PageSizeChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles gridViewResults.PageSizeChanged
        '
    End Sub

Я рассмотрел почти все связанные проблемы здесь, в Stackoverflow, а также другие возможные решения в сообщениях и статьях в Интернете. Любое понимание или предложения будут оценены.


person Nick P    schedule 29.05.2014    source источник
comment
Привет и добро пожаловать в Stackoverflow. Это хороший вопрос для SO, спасибо, что разместили его. Причина, по которой вы до сих пор не получили ответа, скорее всего, связана с реальной проблемой, а не с самим вопросом. В любом случае удачи. Помните, если вы сами нашли решение, вы можете опубликовать его в качестве ответа на свой вопрос. Это может быть очень полезно для других и помогает предотвратить повторные публикации этого вопроса в будущем.   -  person Marcel    schedule 26.06.2014
comment
Вы изучили этот вопрос: stackoverflow.com/q/570294/79485 Хотя это не совсем дубликат, он может содержат полезную для вас информацию.   -  person Marcel    schedule 26.06.2014