Подтвердить что ты не робот

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

У меня есть то, что я считаю, должно быть довольно простой проблемой, но для жизни меня я не вижу своей проблемы. Проблема связана с 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);

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

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

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

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

Спасибо:)


Хорошо, чтобы ответить на запрос выше - он выглядит так, как будто placeholder каким-то образом запутывает ScriptManager.RegisterStartupScript.

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

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

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

4b9b3361

Ответ 1

Я думаю, вы действительно должны использовать контрольную перегрузку в 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 является заполнителем в панели обновления. Заполнитель имеет несколько других элементов управления, включая кнопки.

Это было так, как вы ожидали, я получал предупреждение "Hello" каждый раз, когда я загружал страницу или вызывал обновление панели обновления.

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

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

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

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

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

Ответ 2

У меня возникла проблема с использованием этого в пользовательском элементе управления (на странице это работало нормально); 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);

Ответ 3

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

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

Ответ 4

Решение состоит в том, чтобы поместить скрипты в внешний файл 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 Эта часть того, что я опубликовал некоторое время назад здесь.

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

Ответ 5

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

Аналогичное решение может работать для вас.

Ответ 6

НЕ используйте 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", "");
 }

Ответ 7

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

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

ScriptManager.RegisterClientScriptBlock(Page, Page.GetType(), key, script, **false**);

Ответ 8

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

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

Ответ 9

Иногда он не срабатывает, когда script имеет некоторую синтаксическую ошибку, убедитесь, что синтаксис script и javascript верен.

Ответ 10

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

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

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

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