ASP.NET Tutorial/Custom Controls/CompositeControl

Материал из .Net Framework эксперт
Перейти к: навигация, поиск

Building Composite Controls

   <source lang="csharp">

using System; using System.Web.UI.WebControls; namespace myControls {

   public class RequiredTextBox : CompositeControl
   {
       private TextBox input;
       private RequiredFieldValidator validator;
       public string Text
       {
           get
           {
               EnsureChildControls();
               return input.Text;
           }
           set
           {
               EnsureChildControls();
               input.Text = value;
           }
       }
       protected override void CreateChildControls()
       {
           input = new TextBox();
           input.ID = "input";
           this.Controls.Add(input);
           validator = new RequiredFieldValidator();
           validator.ID = "valInput";
           validator.ControlToValidate = input.ID;
           validator.ErrorMessage = "(Required)";
           validator.Display = ValidatorDisplay.Dynamic;
           this.Controls.Add(validator);
       }
   }

} File: Default.aspx

<%@ Page Language="C#" Trace="true" %> <%@ Register TagPrefix="custom" Namespace="myControls" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server">

   protected void btnSubmit_Click(object sender, EventArgs e)
   {
       lblResults.Text = txtUserName.Text;
   }

</script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server">

   <title>Show RequiredTextBox</title>

</head> <body>

   <form id="form1" runat="server">
   <asp:Label
       ID="lblUserName"
       Text="User Name:"
       AssociatedControlID="txtUserName"
       Runat="server" />
   <custom:RequiredTextBox
       ID="txtUserName"
       Runat="Server" />
   
<asp:Button ID="btnSubmit" Text="Submit" Runat="server" OnClick="btnSubmit_Click" />

   <asp:Label
       id="lblResults"
       Runat="server" />
   </form>

</body> </html></source>


Building Hybrid Controls

   <source lang="csharp">

File: Login.cs using System; using System.Web.UI; using System.Web.UI.WebControls; namespace myControls {

   public class Login : CompositeControl
   {
       private TextBox txtUserName;
       private TextBox txtPassword;
       public string UserName
       {
           get
           {
               EnsureChildControls();
               return txtUserName.Text;
           }
           set
           {
               EnsureChildControls();
               txtUserName.Text = value;
           }
       }
       public string Password
       {
           get
           {
               EnsureChildControls();
               return txtPassword.Text;
           }
           set
           {
               EnsureChildControls();
               txtPassword.Text = value;
           }
       }
       protected override void CreateChildControls()
       {
           txtUserName = new TextBox();
           txtUserName.ID = "txtUserName";
           this.Controls.Add(txtUserName);
           txtPassword = new TextBox();
           txtPassword.ID = "txtPassword";
           txtPassword.TextMode = TextBoxMode.Password;
           this.Controls.Add(txtPassword);
       }
       protected override void RenderContents(HtmlTextWriter writer)
       {
           writer.RenderBeginTag(HtmlTextWriterTag.Tr);
           writer.RenderBeginTag(HtmlTextWriterTag.Td);
           writer.AddAttribute(HtmlTextWriterAttribute.For, txtUserName.ClientID);
           writer.RenderBeginTag(HtmlTextWriterTag.Label);
           writer.Write("User Name:");
           writer.RenderEndTag(); // Label
           writer.RenderEndTag(); // TD
           writer.RenderBeginTag(HtmlTextWriterTag.Td);
           txtUserName.RenderControl(writer);
           writer.RenderEndTag(); // TD
           writer.RenderEndTag();
           writer.RenderBeginTag(HtmlTextWriterTag.Tr);
           writer.RenderBeginTag(HtmlTextWriterTag.Td);
           writer.AddAttribute(HtmlTextWriterAttribute.For, txtPassword.ClientID);
           writer.RenderBeginTag(HtmlTextWriterTag.Label);
           writer.Write("Password:");
           writer.RenderEndTag(); // Label
           writer.RenderEndTag(); // TD
           writer.RenderBeginTag(HtmlTextWriterTag.Td);
           txtPassword.RenderControl(writer);
           writer.RenderEndTag(); // TD
           writer.RenderEndTag(); // TR
       }
       protected override HtmlTextWriterTag TagKey
       {
           get
           {
               return HtmlTextWriterTag.Table;
           }
       }
   }

}</source>


Creating a Default Template

   <source lang="csharp">

File: ArticleWithDefault.cs using System; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; namespace myControls {

   public class ArticleWithDefault : CompositeControl
   {
       private string _title;
       private string _author;
       private string _contents;
       private ITemplate _itemTemplate;
       public string Title
       {
           get { return _title; }
           set { _title = value; }
       }
       public string Author
       {
           get { return _author; }
           set { _author = value; }
       }
       public string Contents
       {
           get { return _contents; }
           set { _contents = value; }
       }
       [TemplateContainer(typeof(ArticleWithDefault))]
       [PersistenceMode(PersistenceMode.InnerProperty)]
       public ITemplate ItemTemplate
       {
           get { return _itemTemplate; }
           set { _itemTemplate = value; }
       }
       protected override void CreateChildControls()
       {
           if (_itemTemplate == null)
               _itemTemplate = new ArticleDefaultTemplate();
           _itemTemplate.InstantiateIn(this);
       }
   }
   public class ArticleDefaultTemplate : ITemplate
   {
       public void InstantiateIn(Control container)
       {
           Label lblTitle = new Label();
           lblTitle.DataBinding += new EventHandler(lblTitle_DataBinding);
           Label lblAuthor = new Label();
           lblAuthor.DataBinding += new EventHandler(lblAuthor_DataBinding);
           Label lblContents = new Label();
           lblContents.DataBinding += new EventHandler(lblContents_DataBinding);
           container.Controls.Add(lblTitle);
           container.Controls.Add(new LiteralControl("
")); container.Controls.Add(lblAuthor); container.Controls.Add(new LiteralControl("
")); container.Controls.Add(lblContents); } void lblTitle_DataBinding(object sender, EventArgs e) { Label lblTitle = (Label)sender; ArticleWithDefault container = (ArticleWithDefault)lblTitle. NamingContainer; lblTitle.Text = container.Title; } void lblAuthor_DataBinding(object sender, EventArgs e) { Label lblAuthor = (Label)sender; ArticleWithDefault container = (ArticleWithDefault)lblAuthor. NamingContainer; lblAuthor.Text = container.Author; } void lblContents_DataBinding(object sender, EventArgs e) { Label lblContents = (Label)sender; ArticleWithDefault container = (ArticleWithDefault)lblContents. NamingContainer; lblContents.Text = container.Contents; } }

} File: Default.aspx <%@ Page Language="C#" %> <%@ Register TagPrefix="custom" Namespace="myControls" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server">

   void Page_Load()
   {
       ArticleWithDefault1.Title = "Creating Templated Databound Controls";
       ArticleWithDefault1.Author = "AAA";
       ArticleWithDefault1.Contents = "content";
       ArticleWithDefault1.DataBind();
   }

</script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server">

   <title>Show Article with Default Template</title>

</head> <body>

   <form id="form1" runat="server">
   <custom:ArticleWithDefault
       id="ArticleWithDefault1"
       Runat="server" />
   </form>

</body> </html></source>


Creating Templated Databound Controls

   <source lang="csharp">

File: DivView.cs using System; using System.Collections; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; namespace MyNamespace {

   public class DivView : CompositeDataBoundControl
   {
       private ITemplate _itemTemplate;
       [TemplateContainer(typeof(DivViewItem))]
       [PersistenceMode(PersistenceMode.InnerProperty)]
       public ITemplate ItemTemplate
       {
           get { return _itemTemplate; }
           set { _itemTemplate = value; }
       }
       protected override int CreateChildControls(IEnumerable dataSource, bool dataBinding)
       {
           int counter = 0;
           foreach (object dataItem in dataSource)
           {
               DivViewItem contentItem = new DivViewItem(dataItem, counter);
               _itemTemplate.InstantiateIn(contentItem);
               Controls.Add(contentItem);
               counter++;
           }
           DataBind(false);
           return counter;
       }
       protected override HtmlTextWriterTag TagKey
       {
           get
           {
               return HtmlTextWriterTag.Div;
           }
       }
   }
   public class DivViewItem : WebControl, IDataItemContainer
   {
       private object _dataItem;
       private int _index;
       public object DataItem
       {
           get { return _dataItem; }
       }
       public int DataItemIndex
       {
           get { return _index; }
       }
       public int DisplayIndex
       {
           get { return _index; }
       }
       protected override HtmlTextWriterTag TagKey
       {
           get
           {
               return HtmlTextWriterTag.Div;
           }
       }
       public DivViewItem(object dataItem, int index)
       {
           _dataItem = dataItem;
           _index = index;
       }
   }

} File: Default.aspx <%@ Page Language="C#" %> <%@ Register TagPrefix="custom" Namespace="MyNamespace" %> <!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 id="Head1" runat="server">

   <style type="text/css">
       .products
       {
           width:500px;
       }
       .products div
       {
           border:solid 1px black;
           padding:10px;
           margin:10px;
       }
   </style>
   <title>Show DivView</title>

</head> <body>

   <form id="form1" runat="server">
   <custom:DivView
       id="lstProducts"
       DataSourceID="srcProducts"
       CssClass="products"
       Runat="Server">
       <ItemTemplate>

<%# Eval("Title") %>

       Director: <%# Eval("Director") %>
       </ItemTemplate>
   </custom:DivView>
   <asp:SqlDataSource
       id="srcProducts"
       ConnectionString="<%$ ConnectionStrings:Products %>"
       SelectCommand="SELECT Title, Director FROM Products"
       Runat="server" />
   
<asp:LinkButton id="lnkReload" Text="Reload" Runat="server" />
   </form>

</body> </html></source>


File: Product.cs

   <source lang="csharp">

using System; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; namespace myControls {

   public class Product : CompositeControl
   {
       private ITemplate _itemTemplate;
       private ProductItem _item;
       public string Name
       {
           get
           {
               EnsureChildControls();
               return _item.Name;
           }
           set
           {
               EnsureChildControls();
               _item.Name = value;
           }
       }
       public Decimal Price
       {
           get
           {
               EnsureChildControls();
               return _item.Price;
           }
           set
           {
               EnsureChildControls();
               _item.Price = value;
           }
       }
       [TemplateContainer(typeof(ProductItem))]
       [PersistenceMode(PersistenceMode.InnerProperty)]
       public ITemplate ItemTemplate
       {
           get { return _itemTemplate; }
           set { _itemTemplate = value; }
       }
       protected override void CreateChildControls()
       {
           _item = new ProductItem();
           _itemTemplate.InstantiateIn(_item);
           Controls.Add(_item);
       }
   }
   public class ProductItem : WebControl, IDataItemContainer
   {
       private string _name;
       private decimal _price;
       public string Name
       {
           get { return _name; }
           set { _name = value; }
       }
       public decimal Price
       {
           get { return _price; }
           set { _price = value; }
       }
       public object DataItem
       {
           get
           {
               return this;
           }
       }
       public int DataItemIndex
       {
           get { return 0; }
       }
       public int DisplayIndex
       {
           get { return 0; }
       }
   }

} File: Default.aspx <%@ Page Language="C#" %> <%@ Register TagPrefix="custom" Namespace="myControls" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server">

   void Page_Load()
   {
       Product1.Name = "Laptop Computer";
       Product1.Price = 1254.12m;
       Product1.DataBind();
   }

</script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server">

   <title>Show Product</title>

</head> <body>

   <form id="form1" runat="server">
   <custom:Product
       id="Product1"
       Runat="Server">
       <ItemTemplate>
       Name: <%# Eval("Name") %>
       
Price: <%# Eval("Price", "{0:c}") %> </ItemTemplate> </custom:Product>
   </form>

</body> </html></source>


Image Rotator

   <source lang="csharp">

File: ImageRotator.cs using System; using System.Collections; using System.Web.UI; using System.Web.UI.WebControls; using System.ruponentModel; namespace myControls {

   [ParseChildren(true, "ImageItems")]
   public class ImageRotator : WebControl
   {
       private ArrayList _imageItems = new ArrayList();
       public ArrayList ImageItems
       {
           get
           {
               return _imageItems;
           }
       }
       protected override void RenderContents(HtmlTextWriter writer)
       {
           if (_imageItems.Count > 0)
           {
               Random rnd = new Random();
               ImageItem img = (ImageItem)_imageItems[rnd.Next (_imageItems.Count)];
               writer.AddAttribute(HtmlTextWriterAttribute.Src, img.ImageUrl);
               writer.AddAttribute(HtmlTextWriterAttribute.Alt, img.AlternateText);
               writer.RenderBeginTag(HtmlTextWriterTag.Img);
               writer.RenderEndTag();
           }
       }
   }
   public class ImageItem
   {
       private string _imageUrl;
       private string _alternateText;
       public string ImageUrl
       {
           get { return _imageUrl; }
           set { _imageUrl = value; }
       }
       public string AlternateText
       {
           get { return _alternateText; }
           set { _alternateText = value; }
       }
   }

}


File: ShowImageRotator.aspx <%@ Page Language="C#" Trace="true" %> <%@ Register TagPrefix="custom" Namespace="myControls" %> <!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 id="Head1" runat="server">

   <title>Show ImageRotator</title>

</head> <body>

   <form id="form1" runat="server">
   <custom:ImageRotator
       id="ImageRotator1"
       Runat="server">
       <custom:ImageItem ImageUrl="Image1.gif" AlternateText="Image 1" />
       <custom:ImageItem ImageUrl="Image2.gif" AlternateText="Image 2" />
       <custom:ImageItem ImageUrl="Image3.gif" AlternateText="Image 3" />
   </custom:ImageRotator>
   </form>

</body> </html></source>


Item Rotator

   <source lang="csharp">

File: ItemRotator.cs using System; using System.Collections; using System.Web.UI; using System.Web.UI.WebControls; using System.ruponentModel; namespace myControls {

   [ParseChildren(true, "Items")]
   public class ItemRotator : CompositeControl
   {
       private ArrayList _items = new ArrayList();
       [Browsable(false)]
       public ArrayList Items
       {
           get { return _items; }
       }
       protected override void CreateChildControls()
       {
           Random rnd = new Random();
           int index = rnd.Next(_items.Count);
           Control item = (Control)_items[index];
           this.Controls.Add(item);
       }
   }
   public class Item : Control
   {
   }

} File: Default.aspx <%@ Page Language="C#" Trace="true" %> <%@ Register TagPrefix="custom" Namespace="myControls" %> <!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 id="Head1" runat="server">

   <title>Show ItemRotator</title>

</head> <body>

   <form id="form1" runat="server">
   <custom:ItemRotator
       id="ItemRotator1"
       Runat="server">
       <custom:item ID="Item1" runat="server">
           First Item
       </custom:item>
       <custom:item ID="Item2" runat="server">
           Second Item
           <asp:Calendar
               id="Calendar1"
               Runat="server" />
       </custom:item>
       <custom:item ID="Item3" runat="server">
           Third Item
       </custom:item>
   </custom:ItemRotator>
   </form>

</body> </html></source>


Performing layout with an HTML table.

   <source lang="csharp">

File: LoginStandards.cs using System; using System.Web.UI; using System.Web.UI.WebControls; namespace myControls {

   public class LoginStandards : CompositeControl
   {
       private TextBox txtUserName;
       private TextBox txtPassword;
       public string UserName
       {
           get
           {
               EnsureChildControls();
               return txtUserName.Text;
           }
           set
           {
               EnsureChildControls();
               txtUserName.Text = value;
           }
       }
       public string Password
       {
           get
           {
               EnsureChildControls();
               return txtPassword.Text;
           }
           set
           {
               EnsureChildControls();
               txtPassword.Text = value;
           }
       }
       protected override void CreateChildControls()
       {
           txtUserName = new TextBox();
           txtUserName.ID = "txtUserName";
           this.Controls.Add(txtUserName);
           txtPassword = new TextBox();
           txtPassword.ID = "txtPassword";
           txtPassword.TextMode = TextBoxMode.Password;
           this.Controls.Add(txtPassword);
       }
       protected override void RenderContents(HtmlTextWriter writer)
       {
           writer.AddStyleAttribute("float", "left");
           writer.RenderBeginTag(HtmlTextWriterTag.Div);
           writer.AddStyleAttribute(HtmlTextWriterStyle.Padding, "3px");
           writer.RenderBeginTag(HtmlTextWriterTag.Div);
           writer.AddAttribute(HtmlTextWriterAttribute.For, txtUserName.ClientID);
           writer.RenderBeginTag(HtmlTextWriterTag.Label);
           writer.Write("User Name:");
           writer.RenderEndTag();
           writer.RenderEndTag();
           writer.AddStyleAttribute(HtmlTextWriterStyle.Padding, "3px");
           writer.RenderBeginTag(HtmlTextWriterTag.Div);
           writer.AddAttribute(HtmlTextWriterAttribute.For, txtPassword.ClientID);
           writer.RenderBeginTag(HtmlTextWriterTag.Label);
           writer.Write("Password:");
           writer.RenderEndTag();
           writer.RenderEndTag();
           writer.RenderEndTag();
           writer.AddStyleAttribute("float", "left");
           writer.RenderBeginTag(HtmlTextWriterTag.Div);
           writer.AddStyleAttribute(HtmlTextWriterStyle.Padding, "3px");
           writer.RenderBeginTag(HtmlTextWriterTag.Div);
           txtUserName.RenderControl(writer);
           writer.RenderEndTag();
           writer.AddStyleAttribute(HtmlTextWriterStyle.Padding, "3px");
           writer.RenderBeginTag(HtmlTextWriterTag.Div);
           txtPassword.RenderControl(writer);
           writer.RenderEndTag();
           writer.RenderEndTag();
           writer.Write("
"); } protected override HtmlTextWriterTag TagKey { get { return HtmlTextWriterTag.Div; } } }

}</source>


Supporting Two-Way Databinding

   <source lang="csharp">

Two-way databinding enables you to extract values from a template. You can use a two-way databinding expression not only to display the value of a data item, but also to update the value of a data item. File: ProductForm.cs using System; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.ruponentModel; using System.Collections.Specialized; namespace myControls {

   public class ProductForm : CompositeControl
   {
       public event EventHandler ProductUpdated;
       private IBindableTemplate _editItemTemplate;
       private ProductFormItem _item;
       private IOrderedDictionary _results;
       public IOrderedDictionary Results
       {
           get { return _results; }
       }
       public string Name
       {
           get
           {
               EnsureChildControls();
               return _item.Name;
           }
           set
           {
               EnsureChildControls();
               _item.Name = value;
           }
       }
       public decimal Price
       {
           get
           {
               EnsureChildControls();
               return _item.Price;
           }
           set
           {
               EnsureChildControls();
               _item.Price = value;
           }
       }
       [TemplateContainer(typeof(ProductFormItem), BindingDirection.TwoWay)]
       [PersistenceMode(PersistenceMode.InnerProperty)]
       public IBindableTemplate EditItemTemplate
       {
           get { return _editItemTemplate; }
           set { _editItemTemplate = value; }
       }
       protected override void CreateChildControls()
       {
           _item = new ProductFormItem();
           _editItemTemplate.InstantiateIn(_item);
           Controls.Add(_item);
       }
       protected override bool OnBubbleEvent(object source, EventArgs args)
       {
           _results = _editItemTemplate.ExtractValues(_item);
           if (ProductUpdated != null)
               ProductUpdated(this, EventArgs.Empty);
           return true;
       }
   }
   public class ProductFormItem : WebControl, IDataItemContainer
   {
       private string _name;
       private decimal _price;
       public string Name
       {
           get { return _name; }
           set { _name = value; }
       }
       public decimal Price
       {
           get { return _price; }
           set { _price = value; }
       }
       public object DataItem
       {
           get { return this; }
       }
       public int DataItemIndex
       {
           get { return 0; }
       }
       public int DisplayIndex
       {
           get { return 0; }
       }
   }

} File: Default.aspx <%@ Page Language="C#" %> <%@ Register TagPrefix="custom" Namespace="myControls" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server">

   void Page_Load()
   {
       if (!Page.IsPostBack)
       {
           ProductForm1.Name = "Laptop";
           ProductForm1.Price = 433.12m;
           ProductForm1.DataBind();
       }
   }
   protected void ProductForm1_ProductUpdated(object sender, EventArgs e)
   {
       lblName.Text = ProductForm1.Results["Name"].ToString();
       lblPrice.Text = ProductForm1.Results["Price"].ToString();
   }

</script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server">

   <title>Show ProductForm</title>

</head> <body>

   <form id="form1" runat="server">
   <custom:ProductForm
       id="ProductForm1"
       Runat="server" OnProductUpdated="ProductForm1_ProductUpdated">
       <EditItemTemplate>
       <asp:Label
           id="lblName"
           Text="Product Name:"
           AssociatedControlID="txtName"
           Runat="server" />
       <asp:TextBox
           id="txtName"
           Text="<%# Bind("Name") %>"
           Runat="server" />
       

<asp:Label id="lblPrice" Text="Product Price:" AssociatedControlID="txtPrice" Runat="server" /> <asp:TextBox id="txtPrice" Text="<%# Bind("Price") %>" Runat="server" />

<asp:Button id="btnUpdate" Text="Update" Runat="server" /> </EditItemTemplate> </custom:ProductForm>

   New Product Name:
   <asp:Label
       id="lblName"
       Runat="server" />
   

New Product Price: <asp:Label id="lblPrice" Runat="server" />
   </form>

</body> </html></source>