Невозможно заставить работать ScriptManager.RegisterStartupScript в WebControl, вложенном в UpdatePanel.

StackOverflow https://stackoverflow.com/questions/802506

Вопрос

У меня, по моему мнению, должна быть довольно простая проблема, но хоть убей, я не могу увидеть свою проблему.Проблема связана с ScriptManager.RegisterStartupScript, который я использовал много раз раньше.

У меня есть сценарий: у меня есть собственный веб-элемент управления, вставленный в страницу.Этот элемент управления (и один или два других) вложены в UpdatePanel.Они вставляются на страницу в PlaceHolder:

<asp:UpdatePanel ID="pnlAjax" runat="server">
  <ContentTemplate>
    <asp:PlaceHolder ID="placeholder" runat="server">
    </asp:PlaceHolder>
    ...

protected override void OnInit(EventArgs e){
  placeholder.Controls.Add(Factory.CreateControl());
  base.OnInit(e);
}

Это единственная панель обновлений на странице.

Для корректной работы элемента управления требуется запуск некоторого начального javascript.Диспетчер вызывает:

ScriptManager.RegisterStartupScript(this, GetType(), 
                                    Guid.NewGuid().ToString(), script, true);

и я также попробовал:

ScriptManager.RegisterStartupScript(Page, Page.GetType(), 
                                    Guid.NewGuid().ToString(), script, true);

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

  1. Вызов RegisterStartupScript из CreateChildControls
  2. Вызов RegisterStartupScript из OnLoad/OnPreRender
  3. Использование разных комбинаций параметров для первых двух параметров (в приведенном выше примере элемент управления — это страница, а тип — GetType(), но я пробовал использовать сам элемент управления и т. д.).
  4. Я пробовал использовать постоянные и новые идентификаторы (не то чтобы я считаю, что это в любом случае должно иметь большое влияние).
  5. Я использовал несколько точек останова и убедился, что строка Register вызывается правильно.

Единственное, что я не пробовал, это использовать саму UpdatePanel в качестве элемента управления и типа, поскольку я не считаю, что элемент управления должен знать о панели обновления (и в любом случае, похоже, не существует хорошего способа получить обновление). панель?).

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

Спасибо :)


Что ж, отвечая на приведенный выше вопрос: похоже, что заполнитель каким-то образом портит ScriptManager.RegisterStartupScript.

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

ScriptManager.RegisterStartupScript(this, GetType(), Guid.NewGuid().ToString(), script, true);

Может ли кто-нибудь пролить свет на то, почему внедренный элемент управления в PlaceHolder не позволяет ScriptManager правильно зарегистрировать сценарий?Я предполагаю, что это может иметь какое-то отношение к жизненному циклу динамических элементов управления, но был бы признателен (насколько мне известно), если для описанного выше существует правильный процесс.

Это было полезно?

Решение

Я думаю, вам действительно следует использовать Контроль перегрузки из RegisterStartupScript.

Я попробовал следующий код в элементе управления сервером:

[ToolboxData("<{0}:AlertControl runat=server></{0}:AlertControl>")]
public class AlertControl : Control{
    protected override void OnInit(EventArgs e){
        base.OnInit(e);
        string script = "alert(\"Hello!\");";
        ScriptManager.RegisterStartupScript(this, GetType(), 
                      "ServerControlScript", script, true);
    }
}

Затем на моей странице у меня есть:

protected override void OnInit(EventArgs e){
    base.OnInit(e);
    Placeholder1.Controls.Add(new AlertControl());
}

Где Placeholder1 — это заполнитель на панели обновления.В заполнителе есть еще несколько элементов управления, включая кнопки.

Это вело себя так, как и следовало ожидать: я получал предупреждение «Привет» каждый раз, когда загружал страницу или вызывал обновление панели обновлений.

Еще одна вещь, на которую вы могли бы обратить внимание, — это подключиться к некоторым событиям жизненного цикла страницы, которые запускаются во время запроса панели обновления:

Sys.WebForms.PageRequestManager.getInstance()
   .add_endRequest(EndRequestHandler);

А PageRequestManager endRequestHandler Событие срабатывает каждый раз, когда панель обновления завершает обновление — это позволит вам вызвать метод для настройки элемента управления.

Мои единственные другие вопросы:

  • Что на самом деле делает ваш сценарий?
  • Вероятно, вы можете увидеть скрипт в HTML внизу страницы (прямо перед закрывающим тегом </form>)?
  • Вы пробовали поставить несколько «внимания (« здесь »);»; Вызовы в вашем сценарии стартапа, чтобы увидеть, правильно ли его вызывают?
  • Вы пробовали Firefox и поджигатель - это сообщает о каких-либо ошибках сценария?

Другие советы

У меня возникла проблема с использованием этого в пользовательском элементе управления (на странице это работало нормально);Button1 находится внутри updatepanel, и scriptmanager на usercontrol.

protected void Button1_Click(object sender, EventArgs e)  
{  
    string scriptstring = "alert('Welcome');";  
    ScriptManager.RegisterStartupScript(this, this.GetType(), "alertscript", scriptstring, true);  
}

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

ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "alertscript", scriptstring, true);

При вызове ScriptManager.RegisterStartupScript параметр «Control» должен быть элементом управления, находящимся в UpdatePanel, который будет обновляться.Вам нужно изменить его на:

ScriptManager.RegisterStartupScript(this, this.GetType(), Guid.NewGuid().ToString(), script, true);

Решение состоит в том, чтобы поместить сценарии во внешний js-файл (назовем его «yourDynamic.js») и перерегистрировать файл каждый раз, когда вы обновляете панель обновлений.

Я использую это в событии updatepanel_prerender:

ScriptManager.RegisterClientScriptBlock(UpdatePanel1, UpdatePanel1.GetType(), "UpdatePanel1_PreRender", _
                   "<script type='text/javascript' id='UpdatePanel1_PreRender'>" & _
                   "include('yourDynamic.js');" & _
                   "removeDuplicatedScript('UpdatePanel1_PreRender');</script>" _
                   , False)

На странице или в каком-то другом включении вам понадобится этот javascript:

// Include a javascript file inside another one.
function include(filename)
{
    var head = document.getElementsByTagName('head')[0];

    var scripts = document.getElementsByTagName('script');
    for(var x=0;x<scripts.length;>    {
        if (scripts[x].getAttribute('src'))
        {
            if(scripts[x].getAttribute('src').indexOf(filename) != -1)
            {
                head.removeChild(scripts[x]);
                break;
            }
        }
    }

    script = document.createElement('script');
    script.src = filename;
    script.type = 'text/javascript';
    head.appendChild(script)
}

// Removes duplicated scripts.
function removeDuplicatedScript(id)
{
    var count = 0;
    var head = document.getElementsByTagName('head')[0];

    var scripts = document.getElementsByTagName('script');
    var firstScript;
    for(var x=0;x<scripts.length;>    {
        if (scripts[x].getAttribute('id'))
        {
            if(scripts[x].getAttribute('id').indexOf(id) != -1)
            {
                if (count == 0)
                {
                    firstScript = scripts[x];
                    count++;
                }
                else
                {
                    head.removeChild(firstScript);
                    firstScript = scripts[x];
                    count = 1;
                }
            }
        }
    }
    clearAjaxNetJunk();
}
// Evoids the update panel auto generated scripts to grow to inifity. X-(
function clearAjaxNetJunk()
{
    var knowJunk = 'Sys.Application.add_init(function() {';
    var count = 0;
    var head = document.getElementsByTagName('head')[0];

    var scripts = document.getElementsByTagName('script');
    var firstScript;
    for(var x=0;x<scripts.length;>    {
        if (scripts[x].textContent)
        {
            if(scripts[x].textContent.indexOf(knowJunk) != -1)
            {
                if (count == 0)
                {
                    firstScript = scripts[x];
                    count++;
                }
                else
                {
                    head.removeChild(firstScript);
                    firstScript = scripts[x];
                    count = 1;
                }
            }
        }
    }
}

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

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

У меня возникла проблема с Page.ClientScript.RegisterStartUpScript: я не использовал панель обновления, но элемент управления был кэширован.Это означало, что мне пришлось вставить скрипт в литерал (или использовать PlaceHolder), чтобы при рендеринге из кеша скрипт включался.

Подобное решение может подойти и вам.

НЕ ИСПОЛЬЗУЙТЕ GUID для ключа

ScriptManager.RegisterClientScriptBlock(this.Page, typeof(UpdatePanel) 
       Guid.NewGuid().ToString(), myScript, true);

и если вы хотите это сделать, вызовите что-то вроде этой функции

 public static string GetGuidClear(string x)
 {
      return x.Replace("-", "").Replace("0", "").Replace("1", "")
              .Replace("2",  "").Replace("3", "").Replace("4", "")
              .Replace("5", "").Replace("6", "").Replace("7", "")
              .Replace("8", "").Replace("9", "");
 }

Что мне помогло, так это зарегистрировать его на странице с указанием типа UpdatePanel, например:

ScriptManager.RegisterClientScriptBlock(this.Page, typeof(UpdatePanel) Guid.NewGuid().ToString(), myScript, true);

Иногда он не срабатывает, если в скрипте есть синтаксическая ошибка. Убедитесь, что синтаксис скрипта и JavaScript верен.

ScriptManager.RegisterStartupScript(this, this.GetType(), Guid.NewGuid().ToString(),script,  true );

Значение параметра «true» в конце ScriptManager.RegisterStartupScript добавит тег JavaScript на вашу страницу:

<script language='javascript' defer='defer'>your script</script >

Если значение будет «false», будет внедрен только скрипт без тега --script--.

Я пробовал много вещей и, наконец, обнаружил, что последний параметр должен быть ложным, и вы должны добавить <SCRIPT> тег в Java-скрипт:

string script = "< SCRIPT >alert('hello!');< /SCRIPT>";

ScriptManager.RegisterClientScriptBlock(Page, Page.GetType(), key, script, **false**);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top