Как проверить, зарегистрирован ли клиентский скрипт во время частичной обратной передачи - PullRequest
13 голосов
/ 13 мая 2010

Ниже приведен код, который я сейчас реализовал.

if (!Page.ClientScript.IsStartupScriptRegistered(Page.GetType(), scriptKey))
{
  ScriptManager scriptManager = ScriptManager.GetCurrent(page);
  if (scriptManager != null && scriptManager.IsInAsyncPostBack)
  {
    //if a MS AJAX request, use the Scriptmanager class
    ScriptManager.RegisterStartupScript(Page, Page.GetType(), scriptKey, script, true);
  }
  else
  {
    //if a standard postback, use the standard ClientScript method
    Page.ClientScript.RegisterStartupScript(Page.GetType(), scriptKey, script, true);
  }
}

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

Проблема в том, что Page.ClientScript.IsStartupScriptRegistered(Page.GetType(), scriptKey) всегда (даже если скрипт зарегистрирован ранее) возвращает false, если это частичная обратная передача. И я не смог найти ScriptManager.IsStartupScriptRegistered (статический) метод. В результате этого дополнительный сценарий генерируется для всех частичных / асинхронных обратных передач.

Обратите внимание, что я использую диспетчер скриптов AjaxControlToolkit версии 4.1, т.е. ToolkitScriptManager на моей главной странице. Но я не думаю, что это как-то связано с этим.

UPDATE

  <asp:UpdatePanel ID="ContactDetailsUpdatePanel" UpdateMode="Conditional" runat="server">
    <Triggers>
      <asp:AsyncPostBackTrigger ControlID="UpdateContactDetailsButton" EventName="Click" />
    </Triggers>
    <ContentTemplate>
      <div id="ContactDetailsContent" class="contact_details_content">
        <div class="customer_contactdetails_left_pane">
          <div class="customer_name_field">
            <asp:Label ID="CustomerNameLabel" runat="server" Text="Customer" />
            <asp:TextBox ID="CustomerNameValue" runat="server" />
          </div>
          <div class="customer_address_field">
            <asp:Label ID="CustomerAddressLabel" runat="server" Text="Address" />
            <asp:TextBox ID="CustomerAddressValue" runat="server" />
            <asp:TextBox ID="CustomerAddressValue1" runat="server" />
            <asp:TextBox ID="CustomerAddressValue2" runat="server" />
            <asp:TextBox ID="CustomerAddressValue3" runat="server" />
          </div>
          <div class="customer_postcode_field">
            <asp:Label ID="CustomerPostcodeLabel" runat="server" Text="Postcode" />
            <asp:TextBox ID="CustomerPostcodeValue" runat="server" />
          </div>
        </div>
        <div class="customer_contactdetails_right_pane">
          <div>
            <asp:Label ID="CustomerContactLabel" runat="server" Text="Contact" />
            <asp:TextBox ID="CustomerContactValue" runat="server" />
          </div>
          <div>
            <asp:Label ID="CustomerTelephoneLabel" runat="server" Text="Telephone" />
            <asp:TextBox ID="CustomerTelephoneValue" runat="server" />
          </div>
          <div>
            <asp:Label ID="CustomerMobileLabel" runat="server" Text="Mobile" />
            <asp:TextBox ID="CustomerMobileValue" runat="server" />
          </div>
          <div>
            <asp:Label ID="CustomerFaxLabel" runat="server" Text="Fax" />
            <asp:TextBox ID="CustomerFaxValue" runat="server" />
          </div>
          <div>
            <asp:Label ID="CustomerEmailLabel" runat="server" Text="Email" />
            <asp:TextBox ID="CustomerEmailValue" runat="server" />
          </div>
          <div>
            <asp:Label ID="CustomerWebLabel" runat="server" Text="Web" />
            <asp:TextBox ID="CustomerWebValue" runat="server" />
          </div>
        </div>
      </div>
      <div class="update_button_field">
        <asp:Button ID="UpdateContactDetailsButton" runat="server" Text="Update" 
          onclick="UpdateContactDetailsButton_Click" />
      </div>          
    </ContentTemplate>    
  </asp:UpdatePanel>

Заранее спасибо.

ПРИМЕЧАНИЕ: Чтобы понять, как продвигается решение этой проблемы, просмотрите комментарии к этому ответу перед ответом.

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

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

Ответы [ 6 ]

10 голосов
/ 17 апреля 2012

Если вы используете это;

Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "noPasswordMatch", script, true);

Затем, чтобы проверить, было ли оно зарегистрировано, вы должны использовать это:

if (Page.ClientScript.IsClientScriptBlockRegistered(this.GetType(), "noPasswordMatch"))

if (Page.ClientScript.IsClientScriptBlockRegistered("noPasswordMatch")) не работает!

4 голосов
/ 07 июля 2011

Я столкнулся с этой же проблемой при написании составного элемента управления в ASP.Net. Когда элемент управления находился внутри панели обновления, Page.ClientScript.IsStartupScriptRegistered не работал. Изнутри метода защищенного переопределения void CreateChildControls () я делал что-то вроде

ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), initializeTokenInputScriptKey, initializeTokenInputScript, true);

Поэтому я столкнулся с ситуацией, аналогичной той, что вы описываете здесь. Что решило мою проблему, так это передача элемента управления и его типа вместо страницы и типа страницы в ScriptManager.RegisterStartupScript. Следовательно код теперь выглядит,

ScriptManager.RegisterStartupScript(this, this.GetType(), initializeTokenInputScriptKey, initializeTokenInputScript, true);

Как только я сделал это изменение, мне больше не нужно проверять Page.ClientScript.IsStartupScriptRegistered. Теперь мой элемент управления работает с панелями обновления или без них. Нет ненужных сплиттеров JS либо. Надеюсь, это поможет

2 голосов
/ 16 ноября 2010

Я написал метод расширения, чтобы проверить, был ли скрипт уже зарегистрирован в ScriptManager. Вы можете использовать тот же принцип для проверки скриптов запуска:

public static bool IsClientScriptBlockRegistered(this ScriptManager sm, string key)
        {
            ReadOnlyCollection<RegisteredScript> scriptBlocks = sm.GetRegisteredClientScriptBlocks();

            foreach (RegisteredScript rs in scriptBlocks)
            {
                if (rs.Key == key)
                    return true;
            }

            return false;
        } 
2 голосов
/ 27 мая 2010

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

1 голос
/ 15 мая 2010

Имейте в виду, что ваша первая строка кода является обратной к возвращаемому значению метода из-за !.

if (!Page.ClientScript.IsStartupScriptRegistered(Page.GetType(), scriptKey))

Если IsStartupScriptRegistered возвращает false, как вы говорите, тогда оператор if должен оценивать true из-за !. Это должно привести к тому, что скрипт будет зарегистрирован как ожидалось.

Ваш код основан на моем ответе , который основан на ASP.NET AJAX 1.0 и ASP.NET 2.0. Это может иметь какое-то отношение к .NET 3.5, хотя я полагаю, что я уже использовал вышеупомянутое уже в более новом проекте, который мы сделали под 3.5, и он работал нормально ...

Можете ли вы опубликовать некоторую разметку для кода?

РЕДАКТИРОВАТЬ: Спасибо за размещение разметки.

Теперь я заметил 2 вещи:

Вы упомянули, что используете ToolkitScriptManager. Это элемент управления, который наследуется от ScriptManager. Я не замечал этого раньше, но ваш код все еще ссылается на ScriptManager напрямую. Вы сказали, что сценарий не работает во время асинхронных обратных передач, поэтому я считаю, что это проблема с вашей ссылкой на ScriptManager. Раньше я никогда не использовал ToolkitScriptManager, поэтому не могу дать вам точный код, но могу сказать, что вам, вероятно, потребуется обновить свой программный код, изменив все ссылки на ScriptManager и его методы / свойства на эквивалентные в ToolkitScriptManager. .

Попробуйте добавить точку останова в операторе if и убедитесь, что она имеет значение true. Я не удивлюсь, если scriptManager равно null или scriptManager.IsInAsyncPostBack равно false, потому что вы используете ToolkitScriptManager.

ScriptManager scriptManager = ScriptManager.GetCurrent(page);
if (scriptManager != null && scriptManager.IsInAsyncPostBack)
{
  //if a MS AJAX request, use the Scriptmanager class
  ScriptManager.RegisterStartupScript(Page, Page.GetType(), scriptKey, script, true);
}

И наконец - ваша разметка выглядит хорошо, за исключением того, что вам не нужен раздел <Triggers>. Триггеры позволяют вам указать элемент управления, который находится за пределами вашей панели обновления, чтобы вызвать частичный рендеринг. Любой дочерний элемент управления панели обновлений в разделе <ContentTemplate> сделает это автоматически. Кнопка, на которую вы нацелены в разделе «Триггеры», уже находится на панели обновления. Хотя я не думаю, что это является причиной вашей проблемы, я все равно устраню ее.

Надеюсь, это поможет.

0 голосов
/ 13 мая 2010

Возможно, вы имели в виду: ClientScriptManager.IsStartupScriptRegistered Method

...