Использование пользовательских элементов управления из других проектов в ASP - PullRequest
5 голосов
/ 02 апреля 2009

Я пытаюсь повторно использовать свои пользовательские элементы управления ASP в других проектах и ​​столкнулся с проблемой. Я прочитал пост Скотту на http://weblogs.asp.net/scottgu/archive/2005/08/28/423888.aspx и попытался следовать его шаблонам, но во время выполнения дочерние элементы управления моих элементов управления не инициализируются.

Моя настройка: Я использую Visual Studio 2008 Я создал решение для хранения элементов управления, которые хочу распространить на несколько других решений. Это решение содержит:

  • проекты библиотек (для кода модели и т. Д.), Назовем это "ClassLibrary"
  • проект WebApp (с моими пользовательскими элементами управления), давайте назовем это "Внутренний"
  • ряд других проектов WebApp, действующих в качестве оболочек для проекта Innermost, давайте рассмотрим один из них и назовем его "Внешний"

Мысль, стоящая за этим, заключается в том, что 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();
        }
    }
}

Внутренне ссылается на проект библиотеки и работает нормально. Это пример 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>

Внешний проект ссылается на 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, я не получаю ошибок, и все работает. Когда я запускаю проект Outer, я получаю NullReferenceException s, сообщая, что дочерние элементы управления Innermost.UserControls.WebUserControlX не установлены.

StackTrace:

[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 элементов управления не настроены должным образом? Даже если я запускаю CreateChildControls() в Init внешних элементов управления, они не создаются. Есть ли какой-то конкретный способ, которым мне нужно скомпилировать проект Innermost для использования в проекте Outer?

Любая помощь будет принята с благодарностью!

1 Ответ

7 голосов
/ 02 апреля 2009

Я не каждый пробовал эту настройку раньше, но я могу предположить, что происходит. UserCotnrols предназначены для загрузки по пути, а не по ссылке. Вы пытаетесь создать их по ссылке. Обратите внимание на разницу между тем, как вы относитесь к ним во внутреннем проекте, и чем он отличается от внешнего проекта. Я полагаю, чтобы это работало, вам нужно обратиться к пути к файлу .ascx.

Быстрый поиск показывает, как это можно сделать в VS 2005, но концепция должна быть такой же в VS 2008. Вы можете найти эту информацию здесь .

Другой вариант - не использовать поверхность конструктора и вместо этого загружать элементы управления, используя метод LoadControl, передавая путь к файлам .ascx.

Редактировать Важная вещь, которую можно извлечь из ссылки, о которой я упоминал выше, заключается в том, что вы должны сделать файлы .ascx доступными для вашего внешнего приложения. Приведенная выше ссылка делает это с помощью команды предварительной сборки, чтобы скопировать файлы .ascx во вложенную папку во внешнем проекте. Думайте о внутреннем проекте, как будто вы собираетесь распространять его. Вы должны отдать не только сборку, но и файлы .ascx. Чтобы пользователи могли его использовать, они должны ссылаться на файлы .ascx, а их проект должен ссылаться на вашу сборку. Вы должны сделать то же самое.

Надеюсь, это немного яснее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...