【问题标题】:Using User Controls from Other Projects in ASP在 ASP 中使用来自其他项目的用户控件
【发布时间】:2010-10-17 02:44:15
【问题描述】:

我正在尝试在其他项目中重新使用我的 ASP 用户控件,但遇到了问题。我在http://weblogs.asp.net/scottgu/archive/2005/08/28/423888.aspx 上阅读了 ScottGu 的帖子并尝试遵循他的模式,但运行时我的控件的子控件没有被初始化。

我的设置: 我正在使用 Visual Studio 2008 我创建了一个解决方案来保存我想要分发给其他几个解决方案的控件。该解决方案包含:

  • 库项目(用于模型代码等),我们称之为“ClassLibrary”
  • 一个 WebApp 项目(带有我的用户控件),我们称之为 “Innermost”
  • 许多其他 WebApp 项目充当 Innermost 项目的 Shell,让我们将其中一个称为 “Outer”

这背后的想法是 Innermost 包含功能,而 Outer 包含使 Innermost 控件在特定框架中工作所需的任何特殊修改。

ClassLibrary 有这样的代码(这全部来自我所做的演示设置,以确保这是一个 ASP 问题,而不是我正在做的其他事情):

using System;

namespace ClassLibrary {
    public class LibraryClass {
        public long getLong() {
            return DateTime.Now.Ticks;
        }

        public string getString() {
            return DateTime.Now.ToString();
        }
    }
}

Innermost 引用了库项目并且工作正常。这是此项目中的 UserControl 示例:

<%@ Control Language="C#" AutoEventWireup="true" 
    CodeBehind="WebUserControl1.ascx.cs" 
    Inherits="Innermost.UserControls.WebUserControl1" %>
<asp:Label ID="testLabel" runat="server"/>

带有代码隐藏:

using System;
using System.Web.UI;
using ClassLibrary;

namespace Innermost.UserControls {
    public partial class WebUserControl1 : UserControl {
        protected void Page_Load(object sender, EventArgs e) {
            LibraryClass c = new LibraryClass();
            testLabel.Text = "Your number is " + c.getLong();
        }
    }
}

我在 Innermost 项目中有一个测试页面,它使用 Innermost 项目的用户控件,通过以下语法注册它们:

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

<%@ Register TagPrefix="inner" TagName="Control1" 
    Src="~/UserControls/WebUserControl1.ascx" %>
<%@ Register TagPrefix="inner" TagName="Control2"
    Src="~/UserControls/WebUserControl2.ascx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
    Control 1:
    <inner:Control1 ID="control1" runat="server" />
    <br />
    Control 2:
    <inner:Control2 ID="control2" runat="server" />
</div>
</form>
</body>
</html>

Outer 项目引用 Innermost 和 ClassLibrary;并包含 UserControls 以及以下最内层控件的注册:

<%@ Control Language="C#" AutoEventWireup="true" 
    CodeBehind="TopControl.ascx.cs" Inherits="Outer.Control.TopControl" %>
<%@ Register TagPrefix="inner" Assembly="Innermost"
    Namespace="Innermost.UserControls" %>
<inner:WebUserControl1 ID="Control1" runat="server"/>
<inner:WebUserControl2 ID="Control2" runat="server"/>

使用简单的代码隐藏: 使用系统; 使用 System.Web.UI;

namespace Outer.Control {
    public partial class TopControl : UserControl {
        public bool ShowType1 { get; set; }

        protected void Page_Load(object sender, EventArgs e) {
            Control1.Visible = ShowType1;
            Control2.Visible = !ShowType1;
        }
    }
}

当我在 Innermost 项目中运行测试页面时,我没有收到任何错误,并且一切正常。当我运行外部项目时,我得到NullReferenceExceptions 告诉我Innermost.UserControls.WebUserControlX 的子控件尚未设置。

堆栈跟踪:

[NullReferenceException: Object reference not set to an instance of an object.]
   Innermost.UserControls.WebUserControl1.Page_Load(Object sender, EventArgs e) in c:\Test\ASP\Innermost\Innermost\UserControls\WebUserControl1.ascx.cs:9
   System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +14
   System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +35
   System.Web.UI.Control.OnLoad(EventArgs e) +99
   System.Web.UI.Control.LoadRecursive() +50
   System.Web.UI.Control.LoadRecursive() +141
   System.Web.UI.Control.LoadRecursive() +141
   System.Web.UI.Control.LoadRecursive() +141
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +627

如果有人想仔细研究一下,我可以提供测试设置作为解决方案。

所以,最后,我的问题是:为什么控件的 ChildControls 没有按预期设置?即使我在外部控件的 Init 中运行 CreateChildControls(),它们也不会被创建。是否有一些特殊的方法需要编译 Innermost 项目以用于 Outer 项目?

任何帮助将不胜感激!

【问题讨论】:

    标签: asp.net dll user-controls reference


    【解决方案1】:

    我以前没有尝试过这种设置,但我可以猜测发生了什么。 UserCotnrols 旨在通过路径加载,而不是通过引用加载。您正在尝试通过引用来创建它们。请注意您在内部项目中引用它们的方式与它与外部项目的不同之处。我相信要使其正常工作,您需要参考 .ascx 文件的路径位置。

    快速搜索显示如何在 VS 2005 中完成此操作,但概念在 VS 2008 中应该相同。您可以找到该信息here

    另一种选择是不使用设计图面,而是使用 LoadControl 方法加载控件,并传入 .ascx 文件的路径。

    编辑 从我上面提到的链接中得到的重要一点是,您必须使外部应用程序可以访问 .ascx 文件。上面的链接通过使用预构建命令将 .ascx 文件复制到外部项目中的子文件夹来实现此目的。把内部项目想象成你要重新分配它。您不仅要放弃程序集,还要放弃 .ascx 文件。为了让用户使用它,他们必须引用 .ascx 文件并让他们的项目引用您的程序集。你也必须做同样的事情。

    我希望这更清楚一点。

    【讨论】:

    • 如果控件存在于不同的应用程序中,看起来是这样,LoadControl 将抛出错误:虚拟路径...映射到另一个应用程序,这是不允许的。
    猜你喜欢
    • 2012-03-26
    • 1970-01-01
    • 2014-04-02
    • 1970-01-01
    • 2011-08-26
    • 1970-01-01
    • 2015-12-19
    • 2023-04-11
    • 2019-08-28
    相关资源
    最近更新 更多