Klass-referenser till dynamiska instanser av User Controls

User Controls är smidiga att använda i .NET och ofta vill man ladda in dem dynamiskt. Då måste man referera till dem med deras egna klasstyp.

I version 1.1 var det lättare än i version 2.0 eftersom alla referenser fanns i samma assembly. Man kunde då använda kod som enligt följande.

MyUserControl_ascx myUserControl = (MyUserControl_ascx)LoadControl("MyUserControl.ascx");
myUserControl.IntProperty = 123;
myPlaceHolder.Controls.Add(myUserControl);

På många projekt som jag konverterar från 1.1 till 2.0 får jag felet:

Det gick inte att hitta typ- eller namnområdesnamnet MyUserControl_ascx (saknas ett using-direktiv eller en sammansättningsreferens?

I version 2.0 har nämligen komplileringsmodellen gjorts om en hel del och varje sida och kontroll kompileras i egna assemblys. Man måste nu tänka på att lägga in en referens på de sidorna som ska kunna använda kontrollens klasstyp. En alternativ lösning kan vara att lägga kontrollen i den speciella App_Code-mappen, men då kan man endast använda "inline-code"-modellen.

Jag tänkte nu visa några ett exempel på hur man kan referera till dynamiskt laddade User Controls, tilldela dem egenskaper och lägga till dem på sidan i en PlaceHolder. Exemplet visar hur man gör detta med både "code behind"- och "inline"-modell.

Det som är viktigt att tänka på är att referera till kontrollen med "Reference"-taggen som i mitt exempel ligger i mappen "ctrl". Observera också att när om kontrollen använder inline-kod så måste prefixet "ASP." användas på referensen till instansen.

Default.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ Reference Control="ctrl/WebUserControl_InlineCode.ascx" %>
<%@ Reference Control="ctrl/WebUserControl_CodeBehind.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>Set Properties to dynamicly loaded UserControls</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:PlaceHolder ID="ph" runat="server" />
</div>
</form>
</body>
</html>

Default.aspx.cs


using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Control ctrl = LoadControl("ctrl/WebUserControl_CodeBehind.ascx");
((WebUserControl_CodeBehind)ctrl).StrProperty = "First string";
ph.Controls.Add(ctrl);

//Add linebreak
ph.Controls.Add(new LiteralControl("<br />"));

Control ctrl2 = LoadControl("ctrl/WebUserControl_InlineCode.ascx");
((ASP.WebUserControl_InlineCode)ctrl2).StrProperty = "Second string";
ph.Controls.Add(ctrl2);
}
}

ctrl/WebUserControl_InlineCode.ascx

<%@ Control Language="C#" ClassName="WebUserControl_InlineCode" %>

<script runat="server">

string strProperty = string.Empty;

public string StrProperty
{
get { return strProperty; }
set { strProperty = value; }
}
void Page_Load()
{
lbl.Text = "Property from inline-code User Control: " + strProperty;
}

</script>
<asp:Label ID="lbl" runat="server" />

ctrl/WebUserControl_CodeBehind.ascx

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="WebUserControl_CodeBehind.ascx.cs" Inherits="WebUserControl_CodeBehind" %>
<asp:Label ID="lbl" runat="server" />

ctrl/WebUserControl_CodeBehind.ascx.cs

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class WebUserControl_CodeBehind : System.Web.UI.UserControl
{
string strProperty = string.Empty;

public string StrProperty
{
get { return strProperty; }
set { strProperty = value; }
}
void Page_Load()
{
lbl.Text = "Property from code-behind User Control: " + strProperty;
}
}


MSDN: "Creating Instances of User Controls Programmatically"

 

Comments

[…] Vi har tidigare gått igenom hur man refererar till instanser av User Controls i koden. Om dessa kontroller är cachade så blir det lite svårare. Speciellt om man ska kunna sätta några properties på dem. […]