вторник, 17 апреля 2012 г.

Эмуляция "Прогресса выполнения" или как показать этот самый прогресс для полного ПостБека(Full PostBack) в АпдейтПанели(UpdatePanel)

Исходные данные.
У нас имеется АпдейтПанель(UpdatePanel). В этой АпдейтПанели у нас две кнопки. По нажатию на каждую кнопку приложение делает что-то. Также у нас имеется АпдейтПрогрес(UpdateProgress) для нашей панели. НО одна из кнопок генерирует полный ПостБек (PostBack).

<%@ Page Title="Home Page" Language="vb" MasterPageFile="~/Site.Master" AutoEventWireup="false" CodeBehind="Default.aspx.vb" Inherits="UpdatePanelProgressEmulation._Default" %>
<%-- It is registration for a web user control that include presentation layout of our progress information. --%>
<%@ Register src="Preloader.ascx"  tagname="Preloader" tagprefix="uc1" %>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
    <asp:ScriptManager ID="ScriptManagerMain" unat="server"></asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanelMain" runat="server">
        <Triggers>
            <%--Register our full postback action for button--%>
            <asp:PostBackTrigger ControlID="btnWithPostBackTrigger" />
        </Triggers>
        <ContentTemplate>
            <%--UpdateProgress - uses ucPreloader. As in the above code.--%>
            <asp:UpdateProgress ID="UpdateProgressMain" EnableViewState="false"    AssociatedUpdatePanelID="UpdatePanelMain" runat="server">
                <ProgressTemplate>
                    <uc1:Preloader    ID="ucPreloader" ClientIDMode="Static"   runat="server" />
                </ProgressTemplate>
            </asp:UpdateProgress>
       
            <asp:Button runat="server" ID="btnWithoutPostBackTrigger" Text="Button without PostBackTrigger " BackColor="#006600" BorderStyle="Solid" BorderColor="#003300" ForeColor="White"/>
            <asp:Button runat="server" ID="btnWithPostBackTrigger" Text="Button with PostBackTrigger" BackColor="#CC0000" BorderStyle="Solid"  BorderColor="Maroon" ForeColor="White" />
          
        </ContentTemplate>
       
    </asp:UpdatePanel>
</asp:Content>

Также у нас имеется контрол Preloader.ascx который  отображает какую-то информацию пока происходит обработка и выполнение запроса.
<%--A simple Div that shows us "Loading" message.--%>
<div style="top:150px; width:100%; left:0px; display:block;position:fixed; z-index:2000;" align="center" >
    <table style=" width:600px; height:200px; z-index:2002; background-color:#f9f9f9; border-style:solid; border-color:Grey; ">
        <tr>
            <td valign="middle" align="center">
                <h1 style=" color:Navy">Loading: 5000 milliseconds...</h1>
            </td>
        </tr>     
    </table>
</div>
Согласно исходным данным, при нажатии кнопки   btnWithPostBackTrigger мы не увидим никакой так называемой  "ПрогрессИнформации". Если же мы нажмем на другую кнопку то  мы увилим эту "ПрогрессИнформацию". Но это не очень удобно... В одном случае приложение информирует нас о том что оно что-то делает, в другом нет. Хотя в обоих случаях приложение занято какими-то вычислениями. Было бы гораздо  удобнее информировать пользователя о работе приложения в обоих случаях, вне зависимости от типов постбека.

Исследование.
Существуют различные способы решить эту проблему. Но я предпочитаю использовать самый простой (для меня)  сопособ. И это эмуляция отображения "ПрогрессИнформации" для АпдейтПанели.

Решение.
Идея в следующем - запускать клиентский  код (JavaScript) по нажатию на нашу btnWithPostBackTrigger. В любом случае этот код будет запущен и исполнен до того момента как запрос уйдет на сервер, обработается там, и вернется назад.  Мы нажимаем кнопку и посредством нашего клиентского кода показываем "ПрогрессИнформацию".  И пока запрос не вернулся от сервера мы видим нашу "ПрогрессИнформацию". При таком подходе нам также не надо думать о том как прятать "ПрогрессИнформацию" когда все закончится, потому что когда  запрос вернется от сервера - вся страница полностью перерисуется (у нас полный постбек) . А так как "ПрогрессИнформацию" у нас по умолчанию спрятана - то она исчезнет автоматически после перерисовки страницы.

Теперь небольшие измения висходном коде для реализации всего вышеописанного...
<div id="divPreloader" style="visibility:hidden;">
      <uc1:Preloader    ID="ucPre"  runat="server" />
</div>
Добавляем этот код где-то за пределами АпдейтПанели. Это то что  пользователь будет видеть при полном постбеке. Я расположил его над АпдейтПанелью. Мы будем находить  и показывать этот  див с помощь клиенсткого скрипта.
И добавим OnClientClick="ShowProgress('divPreloader')" к нашей кнопке btnWithPostBackTrigger. в нашем случае ShowProgress - это название джаваскриптовой функции которая будет показывать то, что нам надо.

Измения в .vbфале...
Private Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
        Dim PageLoadedHandlerScript As String = " function getObject (sId) { if(!sId) return null; else if (document.all && document.all[sId])  return document.all[sId];  else if (document.getElementById)  return document.getElementById(sId); else return null;}" _
         & " function ShowProgress(sId) { var dP = getObject(sId); if (dP != null) { dP.style.visibility = 'visible'; } }"
        Page.ClientScript.RegisterClientScriptBlock(Me.GetType, "getObjectScript", PageLoadedHandlerScript, True)
        btnWithPostBackTrigger.OnClientClick = "ShowProgress('divPreloader')"
End Sub
В этом куске кода мы регистрируем клиентский скрипт на странице. В нем две функции. Первая функция ищет DOM обьект на странице. Вторая функция показывает найденный див. Если хотите используйте свой собственный  JavaScript и jQuery.

Вот и все. Надеюсь это поможет вам.

English version of this  post >>
to sources >>
WWW.LANTERIA.COM