【问题标题】:Use LoadControl to programmatically load WebControl (not UserControl)使用 LoadControl 以编程方式加载 WebControl(不是 UserControl)
【发布时间】:2013-07-25 21:54:40
【问题描述】:

我有一个自定义的 WebControl 类,它代表一个被 li(列表项)元素包围的 HyperLink。我希望能够加载此控件并以编程方式将其添加到页面中。

这是自定义 Web 控件 (ListItemHyperLink.cs):

public class ListItemHyperLink : HyperLink
{
    public string ListItemCssClass { get; set; }

    public override void RenderBeginTag(HtmlTextWriter writer)
    {
        if (!String.IsNullOrWhiteSpace(ListItemCssClass))
        {
            writer.AddAttribute(HtmlTextWriterAttribute.Class, ListItemCssClass);
        }
        writer.RenderBeginTag("li");
        base.RenderBeginTag(writer);
    }

    public override void RenderEndTag(HtmlTextWriter writer)
    {
        base.RenderEndTag(writer);
        writer.RenderEndTag();
    }
}

这是我尝试将其添加到的页面 (Test.aspx):

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Test.aspx.cs" Inherits="Example.Test" %>

<!DOCTYPE html>
<html>
<head runat="server">
    <title>My Page</title>
</head>
<body>
    <form id="Form1" runat="server">
        <ul runat="server" ID="UnorderedList">
        </ul>
    </form>
</body>
</html>

这是我尝试在页面的代码隐藏中动态加载控件 (Test.aspx.cs):

public partial class Test : Page
{
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        var listItemHyperLink = (ListItemHyperLink) LoadControl("~/Controls/ListItemHyperLink.cs");
        listItemHyperLink.Text = "Google";
        listItemHyperLink.NavigateUrl = "http://google.com/";
        listItemHyperLink.ListItemCssClass = "li-class";
        listItemHyperLink.CssClass = "a-class";
        UnorderedList.Controls.Add(listItemHyperLink);
    }
}

当我尝试这个时,我得到以下异常:

无法将“System.Web.Compilation.BuildResultCompiledAssembly”类型的对象转换为“System.Web.Util.IWebObjectFactory”类型。

这个异常在我调用LoadControl()的那一行被抛出。

如何使用LoadControl()(或其他方法)从代码中使用此控件?

【问题讨论】:

    标签: c# asp.net dynamic webforms custom-controls


    【解决方案1】:

    只需实例化您的自定义控件并将其添加到 Controls 集合中。 LoadControl 用于 UserControls。

    var listItemHyperLink = new ListItemHyperLink();
    listItemHyperLink.Text = "Google";
    listItemHyperLink.NavigateUrl = "http://google.com/";
    listItemHyperLink.ListItemCssClass = "li-class";
    listItemHyperLink.CssClass = "a-class";
    UnorderedList.Controls.Add(listItemHyperLink);
    

    【讨论】:

    • 这似乎有效!我想我想太多了……我已经习惯于为 UserControls 调用 LoadControl(),以至于当它不适用于 WebControls 时我感到很沮丧。谢谢!
    【解决方案2】:

    ListItemHyperLink 是一个服务器控件,所以不能像用户控件那样加载它。

    protected void Page_Load(object sender, EventArgs e)
    {
        var listItemHyperLink = new ListItemHyperLink();
        listItemHyperLink.Text = "Google";
        listItemHyperLink.NavigateUrl = "http://google.com/";
        listItemHyperLink.ListItemCssClass = "li-class";
        listItemHyperLink.CssClass = "a-class";
        UnorderedList.Controls.Add(listItemHyperLink);
    }
    

    看到 PageLoad 使用覆盖方法有点奇怪。这是不正常的,除非你有背后的原因。这就像使用 Int32 而不是 int。我只是说;希望你不要介意。

    【讨论】:

    • RE:Page_Load 与 OnLoad - 我更喜欢重写基本方法而不是使用 AutoEventWireup 约定,因为它看起来更干净。 This article 谈到了我喜欢这种方法的许多原因。唯一真正的缺点是您必须记住始终在其中调用该方法的base 版本。我很感激你的关心! :)
    • 几年前我也读过那篇文章。除了旧的 DNN 之外,我通常不会在大多数开源项目中看到这种覆盖。但是,这完全取决于您。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多