Как сохранить блок скрипта при частичной обратной передаче? - PullRequest
7 голосов
/ 20 ноября 2010

Это проблема, с которой я сталкиваюсь в веб-приложении, над которым я сейчас работаю.
Поэтому вместо того, чтобы загромождать вопрос несвязанным кодом, я воссоздал проблему в изолированном упрощенном веб-приложении, которое только демонстрирует эту проблему.
Надеюсь, это поможет в поиске решения.

У меня есть пользовательский веб-элемент управления с таким содержимым:

<% if (ShowAlertScript)
   { %>
       <script type="text/javascript">
           function AlertMe() 
           {
               alert('Hello World!');
           }
       </script>
<% } %>
<input type="button" onclick="AlertMe()" value="Say Hello" />

А в его коде нет ничего, кроме логического определения ShowAlertScript.
Это представляет собой элемент управления, который у меня есть в большом веб-приложении, которое имеет два режима: режим ввода и режим отображения . В режиме ввода он имеет большой блок JavaScript, который полезен только тогда; он делает некоторые интересные вещи, чтобы помочь пользователю вводить информацию.

Схема этого элемента управления на большой картинке выглядит следующим образом:

<asp:ScriptManager runat="server" />
<asp:UpdatePanel runat="server">
  <ContentTemplate>
    <asp:MultiView ActiveViewIndex="0" runat="server" ID="mvw">
      <asp:View runat="server">
        <asp:Button runat="server" ID="btnSwitch" 
            OnClick="btnSwitch_Click" Text="Switch" />
      </asp:View>
      <asp:View runat="server">
        <uc:MyInputControl runat="server" ID="micInput" ShowAlertScript="true" />
      </asp:View>
    </asp:MultiView>
  </ContentTemplate>
</asp:UpdatePanel>

Когда вы нажимаете btnSwitch, он просто переключается на второй вид с пользовательским управлением. Обратите внимание, что ShowAlertScript уже инициализирован для true.
Потенциальный вывод состоит в том, что, поскольку я «показываю сценарий оповещения» в пользовательском элементе управления, функция AlertMe() будет выполняться, когда вы щелкнете по элементу input-button, поскольку он записан в соответствии со встроенным оператором if.

Если вы запустите этот код, который я вам дал, он не будет работать.
Браузер скажет, что не видит функцию AlertMe(); насколько он знает, он не определен. Но если вы уберете UpdatePanel (или отключите частичный рендеринг ScriptManager), он будет отлично работать при полной обратной передаче, когда вы нажмете btnSwitch.

Я хочу, чтобы он работал при частичной обратной передаче, потому что все это - небольшой фрагмент по сравнению с остальной частью страницы, и я не хочу делать полную обратную передачу каждый раз, когда они переключают представления.
По-видимому, ScriptManager даже не беспокоит повторный рендеринг файла ascx для возможных изменений.
Либо ScriptManager недостаточно умен, либо мне не хватает опции, позволяющей ему визуализировать <script>, чтобы я мог вызывать его методы на стороне клиента.

Потенциальный ответ, который кто-то может предложить: «Почему бы вам не извлечь javascript, не поместить его в свой собственный файл .js и не указать ссылку на страницу, чтобы он был доступен для элемента управления?»
Это не будет работать со мной, потому что блок скрипта выполняет некоторую инициализацию и модификацию, которые относятся к этому единственному экземпляру элемента управления, а не ко всем остальным на странице.

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

Спасибо, что прочитали это далеко =)
Ценю любую помощь и вклад.

Ответы [ 2 ]

7 голосов
/ 22 ноября 2010

Чтобы ваш блок сценария правильно поддерживал частичное отображение страницы , вы должны зарегистрировать его на этапе PreRender вашего пользовательского элемента управления, используя метод ScriptManager.RegisterClientScriptBlock () :

protected void Page_PreRender(object sender, EventArgs e)
{
    if (ShowAlertScript) {
        ScriptManager.RegisterClientScriptBlock(this,
            typeof(YourUserControl), "AlertScript",
            @"function AlertMe() 
              {
                  alert('Hello World!');
              }",
            true);
    }
}

(Выше предполагается, что для атрибута AutoEventWireup установлено значение true в директиве @ Control вашего файла ascx.)

Кроме того, поскольку скрипт зарегистрирован в пользовательском элементе управления, но ваш ScriptManager находится на самой странице, вам, вероятно, придется добавить элемент <asp:ScriptManagerProxy> в свой элемент управления. разметка для вышеперечисленного для работы.

1 голос
/ 22 ноября 2010

UpdatePanels фактически изменяет свое содержимое с помощью параметра инфраструктуры AJAX innerHTML в div, соответствующем элементу управления UpdatePanel.

Элементы сценария не выполняются, когда установлен innerHTML.

Следовательно,встроенный (то есть декларативный) JS не может быть выполнен во время частичной обратной передачи.

...