2009-04-02 8 views
4

Ich versuche, meine ASP-Benutzersteuerelemente in anderen Projekten wieder zu verwenden, und habe ein Problem festgestellt. Ich habe den Beitrag von ScottGu auf http://weblogs.asp.net/scottgu/archive/2005/08/28/423888.aspx gelesen und versucht, seinen Mustern zu folgen, aber während der Laufzeit werden die untergeordneten Steuerelemente meiner Steuerelemente nicht initialisiert.Verwenden von Benutzersteuerelementen aus anderen Projekten in ASP

Mein Setup: Ich verwende Visual Studio 2008 Ich habe eine Lösung erstellt, um die Steuerelemente zu halten, die ich an mehrere andere Lösungen verteilen möchte. Diese Lösung enthält:

  • Bibliotheksprojekte (für Modellcode usw.), nennen wir diese "Classlibrary"
  • eine WebApp-Projekt (mit meinem User Controls), nennen wir diese "Innerste"
  • eine Reihe anderer WebApp Projekte als Shells für das innerste Projekt handelt, lassen sie uns eine von ihnen betrachten und nennen es „Outer“

die t Dahinter steht, dass Innermost die Funktionalität enthält und Outer spezielle Modifikationen enthält, die benötigt werden, um Innermost-Controls in einem bestimmten Framework arbeiten zu lassen.

Der Classlibrary hat Code wie folgt (dies alles aus einem Demo-Setup, das ich zu machen gemacht um sicherzustellen, dass es sich um eine ASP Problem wurde, nicht etwas anderes war ich tun):

using System; 

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

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

Innerste das Bibliotheksprojekt referenziert und funktioniert gut. Dies ist ein Beispiel für ein Usercontrol in diesem Projekt:

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

mit Code-Behind:

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(); 
     } 
    } 
} 

ich eine Testseite im Innersten Projekt haben, die die User Controls des Innerste Projekt verwendet durch die Registrierung sie mit folgenden Syntax:

<%@ 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> 

Das äußerte Projekt verweist innerste und Classlibrary; und enthält Benutzersteuerelemente mit der folgenden Registrierung der Innerste Kontrollen:

<%@ 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"/> 

Mit einem einfachen Code-Behind: using System; mit 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; 
     } 
    } 
} 

Wenn ich die Testseite im Innermost-Projekt starte, bekomme ich keine Fehler, und alles funktioniert. Wenn ich das äußere Projekt ausführe, bekomme ich NullReferenceException s, dass die untergeordneten Steuerelemente des Innermost.UserControls.WebUserControlX nicht festgelegt worden sind.

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 

ich den Testaufbau als Lösungen bieten kann, wenn jemand will, um dies einen genaueren Blick haben.

Meine Frage lautet also: Warum werden die ChildControls der Steuerelemente nicht wie erwartet eingerichtet? Selbst wenn ich CreateChildControls() im Init der äußeren Steuerelemente ausführen, werden sie nicht erstellt.Gibt es eine besondere Art, das Innermost-Projekt für das Outer-Projekt zu erstellen?

Jede Hilfe wäre sehr willkommen!

Antwort

6

Ich habe noch nicht alle diese Einstellungen versucht, aber ich kann raten, was passiert. UserCotnrols sollen nach Pfad und nicht nach Referenz geladen werden. Sie versuchen, sie als Referenz zu erstellen. Beachten Sie den Unterschied zwischen der Art, wie Sie im inneren Projekt darauf Bezug nehmen, und dem Unterschied zum äußeren Projekt. Ich glaube, um dies zu erreichen, müssen Sie auf den Pfad der .ascx-Datei verweisen.

Eine schnelle Suche zeigt, wie dies in VS 2005 getan werden kann, aber das Konzept sollte in VS 2008 identisch sein. Sie können diese Informationen here finden.

Eine andere Option wäre, die Entwurfsoberfläche nicht zu verwenden und stattdessen die Steuerelemente mithilfe der LoadControl-Methode zu laden und den Pfad zu den ASCX-Dateien zu übergeben.

bearbeiten Das Wichtigste aus dem Link zu nehmen ich oben erwähnt habe, ist, dass Sie die ASCX-Dateien für Ihre äußere App zugreifbar machen müssen. Der obige Link führt dies durch Verwendung eines Befehls pre-build aus, um die ASCX-Dateien in einen Unterordner im äußeren Projekt zu kopieren. Denken Sie an das innere Projekt, als würden Sie es neu verteilen. Sie müssten nicht nur die Assembly, sondern auch die .ascx-Dateien verschenken. Damit Benutzer sie konsumieren können, müssen sie auf die .ascx-Dateien verweisen und ihr Projekt muss auf Ihre Assembly verweisen. Sie müssen das Gleiche tun.

Ich hoffe, das ist ein wenig klarer.

+0

Wenn Steuerelemente in verschiedenen Anwendungen leben, wie es scheint, wird die LoadControl einen Fehler auslösen: Der virtuelle Pfad ... wird einer anderen Anwendung zugeordnet, die nicht zulässig ist. – Ruslan