Невозможно заставить работать ScriptManager.RegisterStartupScript в WebControl, вложенном в UpdatePanel.
-
03-07-2019 - |
Вопрос
У меня, по моему мнению, должна быть довольно простая проблема, но хоть убей, я не могу увидеть свою проблему.Проблема связана с 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);
Проблема в том, что скрипт работает корректно при первом отображении страницы, но не запускается повторно после частичной обратной передачи.Я пробовал следующее:
- Вызов RegisterStartupScript из CreateChildControls
- Вызов RegisterStartupScript из OnLoad/OnPreRender
- Использование разных комбинаций параметров для первых двух параметров (в приведенном выше примере элемент управления — это страница, а тип — GetType(), но я пробовал использовать сам элемент управления и т. д.).
- Я пробовал использовать постоянные и новые идентификаторы (не то чтобы я считаю, что это в любом случае должно иметь большое влияние).
- Я использовал несколько точек останова и убедился, что строка 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**);