2009-05-21 45 views
7

我有一個從Page繼承的基頁類。我們將其稱爲SpiffyPage。在基頁面類中使用用戶控件

我也有一個名爲SpiffyControl的用戶控件。

然後我有一個aspx頁面,ViewSpiffyStuff.aspx,從SpiffyPage繼承。

在頁面加載時,SpiffyPage類應該將SpiffyControl注入aspx頁面。

的問題是,SpiffyControl是用戶控制和實例,在後面的代碼中一個具有訪問ASP命名空間,有點像:

ASP.controls_spiffycontrol_aspx MyControl; 

但SpiffyPage不是一個aspx頁面,它只是一個基本頁面,因此我無法訪問ASP命名空間,因此我不能實例化一個SpiffyControl以注入它。

我該如何實現目標?

編輯:

很重要的一點是,我必須有實際控制類型的引用,所以我可以將值分配給特定的自定義屬性。這就是爲什麼像LoadControl這樣返回類型Control的函數在這種情況下不起作用的原因。

+2

您可以使用LoadControl,但施放它。 SpiffyControl spiffy =(SpiffyControl)LoadControl(「usercontrol.ascs」); – Geoff 2009-05-21 19:47:00

+0

問題是我不能訪問SpiffyControl類型,所以我也不能施放它 - 如果我可以施放它,我也可以簡單地實例化它。 – 2009-05-21 20:13:02

+0

爲什麼你不能訪問SpiffyControl類型? – Jonas 2009-06-05 16:54:33

回答

10

添加一個基類你SpiffyControl,如:

public class SpiffyBase : UserControl 
{ 
    public void DoIt() 
    { 
     Response.Write("DoIt"); 
    } 
} 

,然後你讓你的SpiffyControl繼承基類,如:

public partial class SpiffyControl : SpiffyBase 

,那麼你應該能夠從BasePage類做​​到這一點:

public class BasePage : Page 
{ 
    protected override void OnLoad(EventArgs e) 
    { 
     var c = Page.LoadControl("SpiffyControl.ascx") as SpiffyBase; 

     Page.Controls.Add(c); 

     c.DoIt(); 
    } 
} 
4

我將在單獨的ASP.NET服務器控件項目中實現SpiffyControl,並從Web應用程序中引用該項目。這樣,控件將不會駐留在ASP名稱空間中,而是位於您選擇的名稱空間中,並像其他任何服務器控件一樣運行。

更新:將用戶控件放入單獨項目中的一個很好的副作用是它們與Web應用程序之間的耦合更加分離,這反過來傾向於使它們更加可重用,並且根據它們的設計,還有更多測試。

1

我不確定這是否會對您有所幫助,但有一種稱爲LoadControl的方法,可以使用usercontrol文件名或usercontrol的類型動態加載用戶控件。該方法位於System.Web.UI.TemplateControl類中。

Control userControl= LoadControl("usercontrol.ascx"); 
panelControl.Controls.Add(userControl); 
0

即使你的基地不是一個ASPX頁面,你可以把它從同一個框架類繼承,如果它是:

public abstract class MyBasePage : System.Web.UI.Page 
{ 

} 
0

假設SpiffyControl和SpiffyPage都在同一個命名空間:

Control spiffyControl = LoadControl("SpiffyControl.ascx"); 
(control as SpiffyControl).SpiffyControlProp1 = true; 
(control as SpiffyControl).SpiffyControlProp2 = "Hello, World!"; 
1

您可以將您的SpiffyControl到庫中 - 這會給它一個更精確的命名空間,並允許您在其他項目中使用它。但是,這有點複雜 - 您已經創建了一個UserControl,但它不會在庫中工作。 UserControls使用代碼隱藏模型 - 它們由兩個文件組成,一個標記和一個代碼。庫似乎不支持代碼隱藏模型,所以你不能使用UserControl。您需要將該用戶控件轉換爲Web控件。

創建一個新的類庫項目。打開項目的屬性並將AssemblyName和Default Namespace設置爲SpiffyLibrary。

現在我們需要轉換你的UserControl。首先,在你的新庫中創建一個類。將它稱爲SpiffyControl,就像您現有的用戶控件一樣,但是使它從System.Web.UI.WebControls.CompositeControl繼承。

其次,打開您現有用戶控件的代碼並複製班級內的所有內容。然後回到新課堂並將其粘貼在裏面。如果您使用任何標準控制事件,則可能需要重命名這些功能以覆蓋適當的事件。例如,

protected void Page_Load(object sender, EventArgs e) 
{ 
    ... 
} 

...應該成爲...

protected override void OnLoad(EventArgs e) 
{ 
    ... 

    base.OnLoad(e); 
} 

三(這是複雜的部分),你需要複製你在SpiffyControl的標記文件有標記。您不能複製它 - 相反,您需要重寫從CompositeControl繼承的CreateChildControls()函數。標記中的每個標記都需要像變量一樣實例化並添加到類的Controls集合中。因此,舉例來說,如果你現有的標記文件是這樣的:

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="SpiffyControl.ascx.cs" Inherits="Controls_SpiffyControl" %> 

<div id="Div1" runat="server"> 
    <asp:Label ID="TextOutput" runat="server" /> 
</div> 

...那麼你的新的CreateChildControls功能應該是這樣的:

HtmlGenericControl Div1; 
Label TextLabel; 

protected override void CreateChildControls() 
{ 
    Div1 = new HtmlGenericControl("div"); 
    this.Controls.Add(Div1); 

    TextLabel = new Label(); 
    Div1.Controls.Add(TextLabel); 

    base.CreateChildControls(); 
} 

注意,控件聲明爲類領域;這樣,它們對所有類方法都是可見的。

一旦您轉換了標記,編譯庫項目並將其添加到您的網站項目的引用。然後打開你的網站的web.config文件並找到system.web/pages/controls部分。這部分應該已經有這樣的標籤:

<add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> 

該標籤是什麼讓你使用ASP核心庫的控件。因此,我們要添加一個只是喜歡它,我們的圖書館:

<add tagPrefix="spiffy" namespace="SpiffyLibrary" assembly="SpiffyLibrary" /> 

現在,在您的網站的任何地方,你可以把類似這樣的標記:

<spiffy:SpiffyControl ID="SpiffyInstance" runat="server" /> 

...,這將從您的自定義庫加載您的網頁控制。

0

您也可以手動定義SpiffyControl的命名空間。爲此,您需要更改代碼隱藏和標記。

在代碼隱藏中,將類包裝在名稱空間塊中。所以如果你的班級是

public partial class Controls_SpiffyControl : System.Web.UI.UserControl 
{ 
    ... 
} 

...然後改變它...

namespace Spiffy 
{ 
    public partial class Controls_SpiffyControl : System.Web.UI.UserControl 
    { 
     ... 
    } 
} 

然後在標記中調整@Control標頭。所以,如果你@Control頭球攻門被

<%@ Control 
    Language="C#" 
    AutoEventWireup="true" 
    CodeFile="SpiffyControl.ascx.cs" 
    Inherits="Controls_SpiffyControl" %> 

...然後將其更改爲...

<%@ Control 
    Language="C#" 
    AutoEventWireup="true" 
    CodeFile="SpiffyControl.ascx.cs" 
    Inherits="Spiffy.SpiffyControl" %> 
0

假設你會在支持反射,你可以使用這些方法的環境中運行。

private void SetValue(Control control, string propertyName, object value) 
{ 
    Type type = control.GetType(); 
    PropertyInfo property = type.GetProperty(propertyName); 
    property.SetValue(control, value, null); 
} 
private object GetValue(Control control, string propertyName) 
{ 
    Type type = control.GetType(); 
    PropertyInfo property = type.GetProperty(propertyName); 
    return property.GetValue(control, null); 
} 

,並調用它是這樣的:

 Control control = this.LoadControl("~/SpiffyControl.ascx"); 
    string propertyName = "Custom1"; 
    object value = "Value"; 

    SetValue(control, propertyName, value); 

如果它被調用了很多,你可能想緩存類型的信息。

你也可以考慮在程序集SpiffyPage中創建一個ISpiffyControl接口,然後讓你的用戶控件實現它。

2

是你們跟我開玩笑,我知道,ASP.NET Web表單是一個痛苦的經歷,但一直寂寂無聞className屬性的,即

<%@ Control ClassName="SpiffyControl" Language="C#" AutoEventWireup="true" CodeFile="SpiffyControl.ascx.cs" Inherits="Controls_SpiffyControl" %> 

因此,最初的例子:

SpiffyControl spiffy = (SpiffyControl)LoadControl("~spiffy.ascx"); 
0

它已被觸及,但一個界面應該工作。讓ISpiffyControl與任何成員/方法,在SpiffyControl.ascx.vb實現它,並在SpiffyPage做到這一點:

Protected Overrides Sub OnLoad(ByVal e As System.EventArgs) 
    MyBase.OnLoad(e) 
    Dim page As New Page 
    Dim path As String = request.ApplicationPath 
    Dim control as UI.Control = page.LoadControl(String.Format _ 
     ("{0}/pathToUserControl/{1}.ascx", path, controlName)) 
    Dim sc As ISpiffyControl = CType(control, ISpiffyControl) 
    sc.DoSomethingSpecial() 
    Me.Controls.Add(sc) 
End Sub 
0

如果我讀這正確的,原來的海報曾在他不能訪問的問題父頁面從其UserControl派生出的基類的類型,而不是其他方式。恰巧我遇到了同樣的問題。

在我的情況下,我的項目中的所有頁面都從同一個基地繼承,所以我不擔心這個事實,即我的用戶控件知道頁面的基類。向建築師道歉。

但是,我解決了這個問題,結合使用1)爲我的用戶控件使用基類,2)使用通用名稱空間。這使得我需要的可見性,因爲由於某種原因,用戶控件的基類仍然看不到頁面的基類的基類類型。

無論如何,我只是想我會分享我的結果,以防他們在未來幫助其他人。

HTH。

相關問題