Проблема жизненного цикла страницы ASP.Net (веб-формы) - различие между загрузкой формы, передачей данных и событиями команд - PullRequest
1 голос
/ 09 октября 2009

Я работаю над сортируемым списком с пейджингом данных. У меня нормально работают списки и пейджинг, но я борюсь с сортировкой. Сама сортировка в порядке; Я могу сортировать по определенному столбцу (ASC или DESC), однако у меня возникают проблемы, когда дело доходит до динамической сортировки, когда пользователь может выбрать столбец и время от времени менять направление сортировки.

Моя основная проблема заключается в том, что в настоящее время генерация отсортированных и разбитых на страницы данных запускается как в обработчике событий Form_Load, так и в обработчике событий Listview_Sorting. В идеале, я бы хотел, чтобы заполнение списка было обработано одним способом для (повторной) загрузки формы и при выборе новой страницы данных, и другим способом, когда пользователь нажимает на заголовок столбца (т.е. когда (повторно) сортировка). К сожалению, когда происходит событие сортировки, выполняется код в Form_Load, а затем выполняется код в ListView_Sorting.

Изначально я был просто неэффективен, чтобы подготовиться к скольжению, но теперь часть кода Form_Load не справляется с тем, что я делаю в обработчике событий Sorting.

Итак, мой вопрос ... как мне разделить обработку этих событий на две группы; как запустить один набор кода, когда страница загружается в первый раз и когда данные выгружаются, когда я пытаюсь отсортировать данные?

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    'Initilize the Sort Column and Direction
    Dim LastColumn As String = If(Session("SortColumn") Is Nothing, "LastWriteTime", Session("SortColumn"))
    Dim SortDirection As SqlClient.SortOrder
    Dim SortDirections As Dictionary(Of String, SqlClient.SortOrder) = Session("SortDirections")

    If SortDirections Is Nothing OrElse Not SortDirections.ContainsKey(LastColumn) Then
        SortDirection = SqlClient.SortOrder.Descending
    Else
        SortDirection = SortDirections(LastColumn)
    End If

    Call GenerateSortedArray(LastColumn, SortDirection)

End Sub

Private Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender

    'bind array to ListView
    Me.lvwMSGs.DataBind()

End Sub

Private Sub lvwMSGs_ItemCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ListViewCommandEventArgs) Handles lvwMSGs.ItemCommand

    Dim file As FileInfo = New FileInfo(e.CommandArgument.ToString) '-- if the file exists on the server

    If e.CommandName = "Stream" Then
        If file.Exists Then 'set appropriate headers
            Response.Clear()
            Response.AddHeader("Content-Disposition", "attachment; filename=" & file.Name)
            Response.AddHeader("Content-Length", file.Length.ToString())
            Response.ContentType = "application/octet-stream"
            Response.WriteFile(file.FullName)
            Response.End()
        Else 'if file does not exist
            Response.Write("This file does not exist.")
        End If
    End If
End Sub

Public Sub lvwMSGs_Sorting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ListViewSortEventArgs) Handles lvwMSGs.Sorting

    Call GenerateSortedArray(e.SortExpression, SqlClient.SortOrder.Ascending)

End Sub

Private Sub GenerateSortedArray(ByVal SortColumn As String, ByVal DefaultSortDirection As SqlClient.SortOrder)
    Dim dirInfo As New DirectoryInfo(Server.MapPath(AppSettings.Item("ContentDir")))
    Dim FileArrayList As New ArrayList(dirInfo.GetFiles("*.msg", SearchOption.TopDirectoryOnly))

    Dim SortDirections As New Dictionary(Of String, SqlClient.SortOrder)

    With FileArrayList
        .TrimToSize()

        SortDirections = Session("SortDirections")
        If Session("SortDirections") Is Nothing OrElse SortDirections.ContainsKey(SortColumn) Then
            'Create dictionary, set to default and store in Session variable
            If Session("SortDirections") Is Nothing Then
                SortDirections = New Dictionary(Of String, SqlClient.SortOrder)
            End If
            SortDirections(SortColumn) = DefaultSortDirection
            Session("SortDirections") = SortDirections

            'Sort data according to preferences
            .Sort(New FileInfoComparer(SortDirections(SortColumn), SortColumn))
        Else
            'retrieve previous sort direction
            SortDirections(SortColumn) = 1 - SortDirections(SortColumn)

            'Sort data according to preferences
            .Sort(New FileInfoComparer(SortDirections(SortColumn), SortColumn))

        End If

    End With

    With Me.lvwMSGs
        .DataSource = FileArrayList
        .ItemPlaceholderID = "ItemPlaceholder"
    End With
End Sub

Ответы [ 3 ]

1 голос
/ 09 октября 2009

Как предполагает awe, достаточно поместить код сортировки при загрузке страницы в блок if (!Page.IsPostBack) { // default page load sorting code here }.

Однако на функциональном уровне вы можете создать универсальную функцию, которая принимает столбец сортировки и направление в качестве параметров и выполняет сортировку за вас. Затем вам нужно просто вызвать эту функцию из загрузки страницы, используя столбец / направление сортировки по умолчанию (условие! Page.IsPostback все еще применяется), и из события ListView_Sorting на основе аргументов события.

Вы могли бы структурировать свой код следующим образом:

Handle Page_Load
{
    if (!Page.IsPostBack)
    {
        // First Time Load Only
        // Identify DEFAULT Sort + DEFAULT Paging values
        // BuildGrid(Default Sort params, Default Paging params);
    }

    // there should be no data grid code in page load on a postback
}

Handle Sorting_Event
{
    // Determine NEW sorting values
    // Fetch Existing Paging values
    // BuildGrid (NEW Sort Params, OLD Paging Params);
}

Handle Paging_Event
{
    // Determine NEW paging values
    // Fetch Existing Sorting values
    // BuildGrid (OLD Sort Params, NEW Paging Params);
}
0 голосов
/ 23 октября 2009

CJM, Чтобы сортировка и разбиение по страницам работали на вас, вы должны сделать следующее:

  • Page_Load: загрузить FileArrayList в переменную-член, если! Page.IsPostBack, sort
  • OnPreRender: привязать FileArrayList к ListView
  • GenerateSortedArray: просто обработать сортировку массива (без привязки)
  • Событие пейджинга: настройка пейджинга

Для этого потребуется переместить часть вашего кода. Так оно и есть, любое добавленное вами событие подкачки не сможет получить доступ к вашему списку.

Кроме того, я бы изменил ваши переменные Session на ViewState, если только вы не ожидаете, что пользователь будет открывать только одну страницу за раз.

0 голосов
/ 09 октября 2009

Вы можете проверить на IsPostback в Page_Load. При первой загрузке IsPostback имеет значение false, а при любых обратных передачах оно равно true.

Если есть проблема с порядком жизненного цикла страницы, вы можете делать вещи, которые зависят от результата обратной передачи в событии Page_PreRender, которое запускается после всех событий обратной передачи управления.

EDIT:
Что если вы переместите вызов на GenerateSortedArray(LastColumn, SortDirection) с Page_Load на Page_PreRender?

Private Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender

    'Initilize the Sort Column and Direction
    Dim LastColumn As String = If(Session("SortColumn") Is Nothing, "LastWriteTime", Session("SortColumn"))
    Dim SortDirection As SqlClient.SortOrder
    Dim SortDirections As Dictionary(Of String, SqlClient.SortOrder) = Session("SortDirections")

    If SortDirections Is Nothing OrElse Not SortDirections.ContainsKey(LastColumn) Then
            SortDirection = SqlClient.SortOrder.Descending
    Else
            SortDirection = SortDirections(LastColumn)
    End If
    GenerateSortedArray(LastColumn, SortDirection)

    'bind array to ListView
    Me.lvwMSGs.DataBind()

End Sub
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...