I have a webcontrol that displays an article in multiple parts. You can jump back and forward between the parts (I call them sheets) by clicking on a label. Each sheet has a label.
The control is used like this:
Expand|Select|Wrap|Line Numbers
- <john:MyControl runat="server">
- <john:Sheet label="Intro">
- This is the first part of the text...
- </john:Sheet>
- <john:Sheet label="Maintext">
- This is the second part of the text...
- </john:Sheet>
- </john:MyControl>
This all works great. The problem is when you put a button inside a sheet, and wire the button to an event. This is were it starts to go wrong. It seems that the first time the control is loaded (before the user has jumped to a different sheet), the button works and the event is called. But if the user jumps to a different sheet and then jump back, the button will not work. At least not the first time you click it. If you click it twice, the event gets called the second time.
This is the code:
*** *** *** ***
---
MyControl.cs
---
Expand|Select|Wrap|Line Numbers
- using System;
- using System.ComponentModel;
- using System.Collections;
- using System.Web;
- using System.Web.UI;
- using System.Web.UI.WebControls;
- using System.Web.UI.HtmlControls;
- namespace John {
- [DefaultProperty("Sheets"),
- ParseChildren(true, "Sheets")]
- public class MyControl : WebControl {
- private ArrayList _sheets;
- private Sheet _selectedSheet = null;
- private HtmlGenericControl rootDiv;
- private HtmlGenericControl _sheetControl;
- private Sheet SelectedSheet {
- get {
- if (_selectedSheet == null) {
- if (Sheets.Count > 0)
- return (Sheet)Sheets[0];
- else
- return null;
- }
- else
- return _selectedSheet;
- }
- set {
- _selectedSheet = value;
- }
- }
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
- PersistenceMode(PersistenceMode.InnerDefaultProperty)]
- public ArrayList Sheets {
- get {
- if (_sheets == null) {
- _sheets = new ArrayList();
- }
- return _sheets;
- }
- }
- protected override void OnInit(EventArgs e) {
- rootDiv = new HtmlGenericControl("div");
- HtmlGenericControl labelsDiv = constructLabels();
- HtmlGenericControl sheet = contructSheet();
- rootDiv.Controls.Add(labelsDiv);
- rootDiv.Controls.Add(sheet);
- this.Controls.Add(rootDiv);
- this.EnableViewState = false;
- base.OnInit(e);
- }
- protected override void OnPreRender(EventArgs e) {
- SelectedSheet.LabelControl.Enabled = false;
- }
- protected void Label_Click(object sender, CommandEventArgs e) {
- int sheetIndex = int.Parse(e.CommandArgument.ToString());
- SelectedSheet = (Sheet)Sheets[sheetIndex];
- _sheetControl.Controls.Clear();
- SelectedSheet.Content.InstantiateIn(_sheetControl);
- }
- protected override void Render(HtmlTextWriter writer) {
- rootDiv.RenderControl(writer);
- }
- private HtmlGenericControl contructSheet() {
- _sheetControl = new HtmlGenericControl("div");
- SelectedSheet.Content.InstantiateIn(_sheetControl);
- return _sheetControl;
- }
- private HtmlGenericControl constructLabels() {
- HtmlGenericControl div = new HtmlGenericControl("div");
- int counter = 0;
- foreach (Sheet sheet in Sheets) {
- counter++;
- LinkButton button = new LinkButton();
- button.Text = sheet.Label;
- button.ID = "btn" + (counter - 1).ToString();
- button.Command += new CommandEventHandler(Label_Click);
- button.CommandArgument = (counter - 1).ToString();
- button.CommandName = "Click";
- sheet.LabelControl = button;
- div.Controls.Add(button);
- div.Controls.Add(new HtmlGenericControl("br"));
- }
- div.Controls.Add(new HtmlGenericControl("hr"));
- return div;
- }
- }
- [TypeConverter(typeof(ExpandableObjectConverter)),
- ParseChildren(true, "Content")]
- public class Sheet {
- private string _label;
- private ITemplate _content = null;
- public LinkButton LabelControl;
- public Sheet()
- : this(String.Empty) {
- }
- public Sheet(string label) {
- _label = label;
- }
- [DefaultValue(""),
- NotifyParentProperty(true)]
- public String Label {
- get { return _label; }
- set { _label = value; }
- }
- [DefaultValue(""),
- NotifyParentProperty(true),
- PersistenceMode(PersistenceMode.InnerDefaultProperty),
- TemplateContainer(typeof(INamingContainer))]
- public ITemplate Content {
- get { return _content; }
- set { _content = value; }
- }
- }
- }
---
MyPage.aspx
---
Expand|Select|Wrap|Line Numbers
- <%@ Page Language="C#" AutoEventWireup="true" CodeFile="MyPage.aspx.cs" Inherits="MyPage" %>
- <%@ Register Namespace="John" TagPrefix="john" %>
- <!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>Untitled Page</title>
- </head>
- <body id="MyPageBody" runat="server" style="background-color: cyan;">
- <form id="form1" runat="server">
- <div>
- <john:MyControl runat="server">
- <john:Sheet label="Intro">
- This is the first part of the text.
- This is the first part of the text.
- This is the first part of the text.<br />
- <asp:Button runat="server" Text="Change page background" OnCommand="ChangePageBackground" />
- </john:Sheet>
- <john:Sheet label="Maintext">
- This is the second part of the text.
- This is the second part of the text.
- This is the second part of the text.<br />
- <asp:Button runat="server" Text="Change page background" OnCommand="ChangePageBackground" />
- </john:Sheet>
- </john:MyControl>
- </div>
- </form>
- </body>
- </html>
---
MyPage.aspx.cs
---
Expand|Select|Wrap|Line Numbers
- 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 MyPage : System.Web.UI.Page {
- protected void ChangePageBackground(object sender, CommandEventArgs e) {
- if (MyPageBody.Style["background-color"] == "cyan")
- MyPageBody.Style["background-color"] = "magenta";
- else
- MyPageBody.Style["background-color"] = "cyan";
- }
- }