在UserControl中定義模版[轉載]

以下這篇文章可能會給我們一些關於用戶控件“繼承”方面的啓發,通過在基礎的UserControl中定製Template,然後在“繼承”的UserControl中將Template做相應的替換就可以達到類似繼承的目的了。
      這篇文章很詳細的說明了如何添加UserControlTemplate,我們只需要在實現TemplateUserControl外再套一個UserControl基本就可以實現UserControl之間的“繼承”了。
More than just the basics with ASP.NET user controls
I was messing around with user controls, and this is like the 3rd time I’ve needed to look this up, so I figured I’d blog about it so I have it written down.
 
As you know, if you have some controls on an ASP.NET page, you could scoop those out and put those into a “User Control” – then drag that user control (the .ascx file) onto your .aspx page and voila. It’s a great way to isolate functionality and code.
 
Now, what if you need to pass the user control some data? Well, in the class of the user control, you can create public properties. For example:
 
private Unit _width = new Unit(400);
 
public Unit Width
{
    get
    {
        return _width;
    }
    set
    {
        _width = value;
    }
}
 
Then, when you create the control on your page, you’ll see that property available, like this:
 
<uc1:SectionHeader ID="sh1" runat="server" Width="400px">
</uc1:SectionHeader>
 
Now, what if you need to pass in something more? Perhaps you want to pass in a chunk of data. Or what if that chunk of data needs to be something even more complex, like ASP.NET controls? Well, there is this kind of obscure, poorly documented concept you can steal from the “templated controls” concept within web controls. You can have a user control, but also have “templates” that you can populate at runtime – with ANYthing that is valid within ASP.NET.
 
Let’s say you have this as your user control:
 
<div class="SectionHeader">
    <asp:PlaceHolder ID="Title" runat="server"></asp:PlaceHolder><br />
    <asp:PlaceHolder ID="Description" runat="server"></asp:PlaceHolder>
</div>


And let’s say we want to fill in Title and Description at runtime, by the caller – and I might want to put a bunch of things into that Description. Like, a calendar control, a gridview, just regular text - anything. What we need to do is create public ITemplate properties like this, in the user control class:
 
private ITemplate _title;
private ITemplate _description;
 
[PersistenceMode(PersistenceMode.InnerProperty), TemplateContainer(typeof(TemplateControl))]
public ITemplate TitleTemplate
{
    get { return _title; }
    set { _title = value; }
}
[PersistenceMode(PersistenceMode.InnerProperty), TemplateContainer(typeof(TemplateControl))]
public ITemplate DescriptionTemplate
{
    get { return _description; }
    set { _description = value; }
}
 
Now, we just need to add some code to the OnInit, so that it will take the controls and/or text that a user entered for the Title and Description templates – and it puts them into the respective PlaceHolders on the user control page:
 
protected override void OnInit(EventArgs e)
{
    base.OnInit(e);
    if (_title != null)
    {
        _title.InstantiateIn(Title);
    }
    if (_description != null)
    {
        _description.InstantiateIn(Description);
    }
}
 
Note that the Title and Description up there, are the references to the placeholders on the page. So this is where it assigns what the user passed in – to the placeholders on your user control.
 
Lastly, add the attribute ParseChildren to the UserControl class, like this:
 
[ParseChildren(true)]
public partial class SectionHeader : System.Web.UI.UserControl
{
 
This tells intellisense on the caller page, to look for child objects (which TitleTemplate and DescriptionTemplate will be “templates” that you put in between the opening and closing tag of the control). So ParseChildren will just make sure it acts correctly when you create the control on the page.
 
When you do all this, this is what this will look like (and Intellisense supports this too) on the consuming side:
 
<uc1:SectionHeader ID="sh1" runat="server" Width="400px">
    <TitleTemplate>This is the title</TitleTemplate>
    <DescriptionTemplate>
        This is the description, and this has have controls in them
        too. For example:
<asp:Calendar ID="cal1" runat="server">
</asp:Calendar>
    </DescriptionTemplate>
</uc1:SectionHeader>
 
So this is quite a powerful and easy way to encapsulate and segregate UI functionality. Plus, it’s like a zillion times easier than manually rendering your own WebControl which is compiled in a .dll – which is nice, but there is no user interface, and you have to do all of your control creation programmatically. You have to figure that you are usually writing a custom control because you need to do something complicated - so that's the last place you want to be stuck without an interface!
 
發佈了16 篇原創文章 · 獲贊 1 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章