I'm working with Templated User Control's. In the final markup of the control, the data is being accessed by the Container keyword. I'm using the word 'keyword' freely, because I do not understand whether this is a keyword, or where the Container word is coming from. Below is an example from my book.
//Address User Control markup
<%@ Control Language="C#" AutoEventWireup="true"
CodeFile="AddressUcTemplated.ascx.cs" Inherits="AddressUcTemplated" %>
<asp:PlaceHolder runat="server"
ID="PlaceHolderAddressTemplate">
</asp:PlaceHolder>
--
//Address User Control code-behind
public partial class AddressUcTemplated :
System.Web.UI.UserControl
{
protected void Page_Init(object sender, EventArgs e)
{
//clear the controls from the placeholder
PlaceHolderAddressTemplate.Controls.Clear();
if (LayoutTemplate == null)
{
PlaceHolderAddressTemplate.Controls.Add(
new LiteralControl("No template defined."));
}
else
{
AddressUcContainer container = new
AddressUcContainer(this.Address);
this.LayoutTemplate.InstantiateIn(container);
//add the controls to the placeholder
PlaceHolderAddressTemplate.Controls.Add(container);
}
}
[PersistenceMode(PersistenceMode.InnerProperty)]
[TemplateContainer(typeof(AddressUcContainer))]
public ITemplate LayoutTemplate { get; set; }
public Address Address { get; set; }
}
--
//Naming Container Class
public class AddressUcContainer : Control, INamingContainer
{
public AddressUcContainer(Address address)
{
this.Address = address;
}
public Address Address { get; set; }
}
--
//Page using the user control; the Container keyword is confusing me in the below //statement
...
<%@ Register src="AddressUcTemplated.ascx" tagname="AddressUcTemplated"
tagprefix="uc1" %>
<uc1:AddressUcTemplated ID="AddressUcTemplated1"
runat="server" AddressType="H开发者_JAVA技巧ome">
<LayoutTemplate>
<h1>Edit Home Address</h1>
<table>
<tr>
<td>Address Line 1:</td>
<td>
<asp:TextBox ID="TextBoxAddress" runat="server"
Text="<%#Container.Address.AddressLine1%>"></asp:TextBox>
...
My example code is as follows:
<asp:Repeater runat="server">
<ItemTemplate><%# Container.DataItem %></ItemTemplate>
</asp:Repeater>
Intellisense states that Container is a field/variable of type RepeaterItem
. The variable-part tells me that this is some special parsing, since it would most probably been a property if it was public stuff.
Anyway, my code is parsed into, amongst other, the following databinding code:
public void __DataBind__control4(object sender, EventArgs e) {
var target = (DataBoundLiteralControl)sender;
var Container = (RepeaterItem)target.BindingContainer;
target.SetDataBoundString(0, Convert.ToString(Container.DataItem, CultureInfo.CurrentCulture));
}
<%# ... %>
is a DataBoundLiteralControl, and Container
is the variable that's exposed to intellisense. This also shows that there's a target
variable, which does not show up in intellisense, but compiles without any problems. Note that this also gives you access to everything private in the generated class, like __fileDependencies
.
<%# target %>
works, while <%# dummy %>
doesn't. And while at it, <%# __DataBind__control4(null, null) %>
creates two compilation errors, 1) "The best overloaded method match for 'System.Convert.ToString(object, System.IFormatProvider)' has some invalid arguments" and 2) "Argument 1: cannot convert from 'void' to 'object'".
This looks like a simple case of whatever is written between <%# ... %>
is placed in Convert.ToString(..., CultureInfo.CurrentCulture)
. It's probably more advanced, involving different ControlBuilders, TemplateParsers, and an ounce of magic, but I think my abstraction works well enough to understand this.
精彩评论