使用LoadControl方法(Type,object [])动态加载UserControl

22

我试图通过页面方法返回用户/服务器控件的HTML表示。当我调用接受用户控件虚拟路径的重载时,它可以正常工作,但是当我尝试调用接受类型的重载时,它无法正常工作。以下是示例代码。有什么建议吗?

[WebMethod]
public static string LoadAlternates(string productId, string pnlId)
{
    object[] parameters = new object[] { pnlId, productId };
    return ControlAsString(typeof(PopupControl), parameters);
}

private static string ControlAsString(Type controlType, object[] parameters)
{
    Page page = new Page();
    UserControl controlToLoad;
    /*
     *calling load control with the type results in the 
     *stringwriter returning an empty string
    */

    controlToLoad = page.LoadControl(controlType, parameters) as UserControl;
    /*
     *However, calling LoadControl with the following overload
     *gives the correct result, ie the string rep. of the control.
    */
     controlToLoad = page.LoadControl(@"~/RepeaterSamples/PopupControl.ascx") as UserControl;

    //some more code, then this... 
    page.Controls.Add(controlToLoad);

    StringWriter sw = new StringWriter();
    HttpContext.Current.Server.Execute(page, sw, false);
    return sw.ToString();
}

请问有什么原因会导致这个StringWriter返回一个空字符串吗?需要指出的是,无论选择哪种方法调用LoadControl,所有的“页面”生命周期都会正确执行。

我想补充一点 - 我必须使用LoadControl(Type, object[])重载。 :(

3个回答

25

MSDN LoadControl页面的底部有这样一段注释:

描述
使用Page.LoadControl(Type, Object[])加载用户控件的页面似乎不会创建ascx文件中添加的子元素。使用Page.LoadControl(String)按预期工作。

评论
感谢您提交此问题。我们正在调查,将在获得更多信息时提供更新。

-Web平台和工具团队
Microsoft于2005年8月6日上午11:08发布
这是有意设计的,因为“TestUC”类型实际上是partial类使用的基类型,它不包含正确的代码来实例化TextBox1引用,该引用实际上在派生类型中定义。有两种解决方法:1. 使用LoadControl(“TestControl.ascx”),实际上它与LoadControl(type)的行为相同,但它实例化了派生类型,后者知道如何实例化TextBox1。2. 使用单个文件页并向页面添加“<%@ Reference %>”指令以引用用户控件,并将类名分配给ascx页面。然后可以安全地使用LoadControl(type)

感谢您报告此问题。
Web平台和工具团队。Microsoft于2005年6月14日下午6:31发布


7

那个重载实例化了基类,但没有实例化其上的任何控件,所以它不起作用。

如果您感兴趣,我在博客文章中快速介绍了一种传递参数的解决方法。


1
嗨,我可以在任何情况下向控件传递参数。但是我必须使用控件类型来加载控件。 - abjbhat
你不能在字符串方法中使用参数,但如果你需要按类型执行操作,这并没有什么帮助。为什么你需要使用其他重载呢?我唯一能想到的是反射工作重载并在自己的代码中复制它所做的事情。 - Steven Robbins

0

如果您想完全呈现控件,一种方法是使用LoadControl实例化控件,然后将其暂时添加到另一个控件或页面本身的控件集合中。这将初始化该控件的生命周期并引发所有正确的事件。完成此操作后,您可以从中获取呈现的HTML或所需内容。

是的,这是一种hack方法,但在紧急情况下它会起作用。


1
我不确定我理解了你的意思,但他不是已经将控件添加到页面的控件集合中了吗:<pre><code> page.Controls.Add(controlToLoad); </code></pre> - Ahmed
1
我知道这个答案是很久以前的,但你能详细说明一下吗,安德鲁?或者给我指一篇关于这个解决方法的文章?我正在尝试使用带有类型参数的LoadControl,我的意图是将加载的控件添加到一个PlaceHolder中,所以对我来说并不是那么大的问题。老实说,对我来说,使用路径到控件的魔术字符串(另一种选择)似乎更像是一种hack!提前致谢。 - WickyNilliams

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接