Asp.net 将其他内容从用户控件添加到已知内容占位符中

Asp.net 将其他内容从用户控件添加到已知内容占位符中,asp.net,user-controls,Asp.net,User Controls,我有一个UserControl,它有一些javascript,我想注入到一个已知的ContentPlaceHolder中 我希望执行以下操作,但当我附加控件以将控件添加到找到的控件时,我得到一个异常,该异常表示我无法在Init、Load或PreRender事件中修改控件集合: “UserControl.ascx” <%@ Control Language="C#" %> <asp:Checkbox runat="server" id="checkBox"/> <app:

我有一个
UserControl
,它有一些javascript,我想注入到一个已知的
ContentPlaceHolder

我希望执行以下操作,但当我附加控件以将控件添加到找到的控件时,我得到一个异常,该异常表示我无法在Init、Load或PreRender事件中修改控件集合:

“UserControl.ascx”

 <%@ Control Language="C#" %>
 <asp:Checkbox runat="server" id="checkBox"/>
 <app:JavascriptInjector runat="server" InjectInto="ScriptPlaceHolder">
      $(function(){ $('#<%= checkBox.ClientID %>').click(function() { ... });
 </script></app:JavascriptInjector>

$(function(){$('#')。单击(function(){…});

“JavascriptInjector.cs”

使用系统;
使用系统诊断;
使用System.Linq;
使用System.Web.UI;
使用System.Web.UI.WebControl;
公共类JavascriptInjector:占位符
{
公共字符串注入
{
获取{将this.ViewState[“InjectInto”]作为字符串返回;}
设置{this.ViewState[“InjectInto”]=value;}
}
受保护的覆盖无效OnInit(事件参数e)
{
碱基.奥尼特(e);
this.PreRender+=this.\u PreRender;
}
私有void\uuu预渲染(对象发送方,事件参数e)
{
if(string.IsNullOrEmpty(this.InjectInto))
{
有规律地去执行;
}
var injectInto=this.findcontrolly(this.Page);
if(injectInto==null)
{
有规律地去执行;
}
injectInto.Controls.Add(此);
返回;
执行规则:
Debug.WriteLine(“定期执行”);
}
以递归方式查找专用控件(当前控件)
{
var found=current.FindControl(this.InjectInto);
如果(找到!=null)
{
发现退货;
}
foreach(current.Controls.Cast()中的var子级)
{
递归返回此.findControl(子级);
}
返回null;
}
}

我找到了答案。下面的
JavascriptInjector
类可以工作,尽管我不知道在
PreRender
中调用render方法会有什么影响。我还认为我可能需要做些什么来确定基本应用程序正在使用哪种类型的
HtmlTextWriter

“JavaScriptInjector.cs”

使用系统;
使用System.IO;
使用System.Linq;
使用System.Web.UI;
使用System.Web.UI.WebControl;
公共类JavascriptInjector:占位符
{
私人学校定期举办;
公共字符串注入
{
获取{将this.ViewState[“InjectInto”]作为字符串返回;}
设置{this.ViewState[“InjectInto”]=value;}
}
受保护的覆盖无效OnInit(事件参数e)
{
碱基.奥尼特(e);
this.PreRender+=this.\u PreRender;
}
受保护的覆盖无效渲染(HtmlTextWriter编写器)
{
如果(此执行规则)
{
base.Render(writer);
}
}
私有void\uuu预渲染(对象发送方,事件参数e)
{
if(string.IsNullOrEmpty(this.InjectInto))
{
有规律地去执行;
}
var injectInto=this.findcontrolly(this.Page);
if(injectInto==null)
{
有规律地去执行;
}
PerformRegularly=假;
使用(var stringWriter=new stringWriter())
使用(var writer=newhtmltextwitter(stringWriter))
{
base.Render(writer);
writer.Flush();
添加(新的LiteralControl(stringWriter.GetStringBuilder().ToString());
}
this.Controls.Clear();
返回;
performRegularly:this.performRegularly=true;
}
以递归方式查找专用控件(当前控件)
{
var found=current.FindControl(this.InjectInto);
如果(找到!=null)
{
发现退货;
}
foreach(current.Controls.Cast()中的var子级)
{
递归返回此.findControl(子级);
}
返回null;
}
}

只是好奇……有什么原因不能像ScriptManager.RegisterScriptBlock()那样做吗?然后我需要将js作为嵌入式资源插入,与usercontrol一起更易于管理,而且我更喜欢将所有javascript转储到文档底部。有人应该将其放在nuget上。非常有用。
using System;
using System.Diagnostics;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;

public class JavascriptInjector : PlaceHolder
{
    public string InjectInto
    {
        get { return this.ViewState["InjectInto"] as string; }
        set { this.ViewState["InjectInto"] = value; }
    }

    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);

        this.PreRender += this.__PreRender;
    }

    private void __PreRender(object sender, EventArgs e)
    {
        if (string.IsNullOrEmpty(this.InjectInto))
        {
            goto performRegularlly;
        }

        var injectInto = this.FindControlRecursively(this.Page);

        if (injectInto == null)
        {
            goto performRegularlly;
        }

        injectInto.Controls.Add(this);

        return;

        performRegularlly:

        Debug.WriteLine("performing regularlly");
    }

    private Control FindControlRecursively(Control current)
    {
        var found = current.FindControl(this.InjectInto);

        if (found != null)
        {
            return found;
        }

        foreach (var child in current.Controls.Cast<Control>())
        {
            return this.FindControlRecursively(child);
        }

        return null;
    }
}
using System;
using System.IO;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;

public class JavascriptInjector : PlaceHolder
{
    private bool performRegularlly;

    public string InjectInto
    {
        get { return this.ViewState["InjectInto"] as string; }
        set { this.ViewState["InjectInto"] = value; }
    }

    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);

        this.PreRender += this.__PreRender;
    }

    protected override void Render(HtmlTextWriter writer)
    {
        if (this.performRegularlly)
        {
            base.Render(writer);
        }
    }

    private void __PreRender(object sender, EventArgs e)
    {
        if (string.IsNullOrEmpty(this.InjectInto))
        {
            goto performRegularlly;
        }

        var injectInto = this.FindControlRecursively(this.Page);

        if (injectInto == null)
        {
            goto performRegularlly;
        }

        performRegularlly = false;

        using (var stringWriter = new StringWriter())
        using (var writer = new HtmlTextWriter(stringWriter))
        {
            base.Render(writer);

            writer.Flush();

            injectInto.Controls.Add(new LiteralControl(stringWriter.GetStringBuilder().ToString()));
        }

        this.Controls.Clear();

        return;

        performRegularlly: this.performRegularlly = true;
    }

    private Control FindControlRecursively(Control current)
    {
        var found = current.FindControl(this.InjectInto);

        if (found != null)
        {
            return found;
        }

        foreach (var child in current.Controls.Cast<Control>())
        {
            return this.FindControlRecursively(child);
        }

        return null;
    }
}