S
Sam
I have a custom control (MyTextBox - taken from Microsoft website)
that implements the IPostBackDataHandler interface. It is added to
the controls collection of a placeholder control during the Page Load
of a main ASPX page. Now if we debug the MyTextBox, we find the order
of events like so (during a Posback, of course): OnInit -> OnLoad ->
LoadPostData.
My question is why does the LoadPostData occur *after* the OnLoad
instead of before?
Now I know about the conventional wisdom that says this is a "Begin
ProcessPostData Second Try" issue. That controls added during page
load will have LoadPostData called *after* their page loads and not
before. But my question is the following. Given that:
1) The newly added control (MyTextBox) plays catch up when added to
the controls collection on Page Load of the main form, and
2) When the newly added control's Init method is called (while playing
catchup) it has a UniqueID that matches the name key in the Forms
collection and a value with the correct submitted textbox data (I've
verified this by inserting breakpoints in MyTextBox),
Thefore:
Why isn't LoadPostData called between the Init and Load events when
the control is added to the control tree? All the preconditions are
there - MyTextBox implements IPostBackDataHandler and has a UniqueID
that matches the Form's name collection. This is true at least during
the Init event of MyTextBox. So it seems to me that the next event to
be fired for MyTextBox would be LoadPostData. But that doesn't happen
(at least not until *after* PageLoad).
BTW, Assigning an ID to MyTextBox on the Init method of the main page
gives the exact same results (except of course the MyTextBox ID is
different).
It sure would make it a lot easier on me if it fired the LoadPostEvent
when it usually does. Calling it *after* the PageLoad of the main
page seems a bit hackish on Microsoft's part. Can anyone shed some
more light on why the internals work the way they do? And is there an
easy way to fix it in my code below?
Thanks for considering.
-Sam
Code follows:
-------
<%@ Page language="c#" Codebehind="Test.aspx.cs"
AutoEventWireup="false" Inherits="Test" %>
<html>
<body>
<form id="Form1" method="post" runat="server">
<asp
laceHolder id=holder runat=server></asp
laceHolder>
</form>
</body>
</html>
------
using System;
using System.Web.UI.WebControls;
public class Test : System.Web.UI.Page
{
private MyTextBox txtBox = new MyTextBox();
private Button btnPress = new Button();
protected PlaceHolder holder;
override protected void OnInit(EventArgs e)
{
InitializeComponent();
base.OnInit(e);
}
protected override void OnLoad(EventArgs e)
{
this.holder.Controls.Add(txtBox);
base.OnLoad (e);
}
private void InitializeComponent()
{
holder.Controls.Add(btnPress);
btnPress.Text = "Do Postback";
}
}
-------
using System;
using System.Web;
using System.Web.UI;
using System.Collections.Specialized;
public class MyTextBox: Control, IPostBackDataHandler
{
private String text = String.Empty;
public String Text
{
get
{
return text;
}
set
{
text = value;
}
}
public event EventHandler TextChanged;
protected override void OnLoad(EventArgs e)
{
base.OnLoad (e);
}
protected override void OnInit(EventArgs e)
{
base.OnInit (e);
Page.RegisterRequiresPostBack(this);
}
public virtual bool LoadPostData(string postDataKey,
NameValueCollection values)
{
String presentValue = Text;
String postedValue = values[postDataKey];
if (!presentValue.Equals(postedValue))
{
Text = postedValue;
return true;
}
return false;
}
public virtual void RaisePostDataChangedEvent()
{
OnTextChanged(EventArgs.Empty);
}
protected virtual void OnTextChanged(EventArgs e)
{
if (TextChanged != null)
TextChanged(this,e);
}
protected override void Render(HtmlTextWriter output)
{
output.AddAttribute(HtmlTextWriterAttribute.Type, "text");
output.AddAttribute(HtmlTextWriterAttribute.Value, this.Text);
output.AddAttribute(HtmlTextWriterAttribute.Name, this.UniqueID);
output.RenderBeginTag(HtmlTextWriterTag.Input);
output.RenderEndTag();
}
}
}
that implements the IPostBackDataHandler interface. It is added to
the controls collection of a placeholder control during the Page Load
of a main ASPX page. Now if we debug the MyTextBox, we find the order
of events like so (during a Posback, of course): OnInit -> OnLoad ->
LoadPostData.
My question is why does the LoadPostData occur *after* the OnLoad
instead of before?
Now I know about the conventional wisdom that says this is a "Begin
ProcessPostData Second Try" issue. That controls added during page
load will have LoadPostData called *after* their page loads and not
before. But my question is the following. Given that:
1) The newly added control (MyTextBox) plays catch up when added to
the controls collection on Page Load of the main form, and
2) When the newly added control's Init method is called (while playing
catchup) it has a UniqueID that matches the name key in the Forms
collection and a value with the correct submitted textbox data (I've
verified this by inserting breakpoints in MyTextBox),
Thefore:
Why isn't LoadPostData called between the Init and Load events when
the control is added to the control tree? All the preconditions are
there - MyTextBox implements IPostBackDataHandler and has a UniqueID
that matches the Form's name collection. This is true at least during
the Init event of MyTextBox. So it seems to me that the next event to
be fired for MyTextBox would be LoadPostData. But that doesn't happen
(at least not until *after* PageLoad).
BTW, Assigning an ID to MyTextBox on the Init method of the main page
gives the exact same results (except of course the MyTextBox ID is
different).
It sure would make it a lot easier on me if it fired the LoadPostEvent
when it usually does. Calling it *after* the PageLoad of the main
page seems a bit hackish on Microsoft's part. Can anyone shed some
more light on why the internals work the way they do? And is there an
easy way to fix it in my code below?
Thanks for considering.
-Sam
Code follows:
-------
<%@ Page language="c#" Codebehind="Test.aspx.cs"
AutoEventWireup="false" Inherits="Test" %>
<html>
<body>
<form id="Form1" method="post" runat="server">
<asp
</form>
</body>
</html>
------
using System;
using System.Web.UI.WebControls;
public class Test : System.Web.UI.Page
{
private MyTextBox txtBox = new MyTextBox();
private Button btnPress = new Button();
protected PlaceHolder holder;
override protected void OnInit(EventArgs e)
{
InitializeComponent();
base.OnInit(e);
}
protected override void OnLoad(EventArgs e)
{
this.holder.Controls.Add(txtBox);
base.OnLoad (e);
}
private void InitializeComponent()
{
holder.Controls.Add(btnPress);
btnPress.Text = "Do Postback";
}
}
-------
using System;
using System.Web;
using System.Web.UI;
using System.Collections.Specialized;
public class MyTextBox: Control, IPostBackDataHandler
{
private String text = String.Empty;
public String Text
{
get
{
return text;
}
set
{
text = value;
}
}
public event EventHandler TextChanged;
protected override void OnLoad(EventArgs e)
{
base.OnLoad (e);
}
protected override void OnInit(EventArgs e)
{
base.OnInit (e);
Page.RegisterRequiresPostBack(this);
}
public virtual bool LoadPostData(string postDataKey,
NameValueCollection values)
{
String presentValue = Text;
String postedValue = values[postDataKey];
if (!presentValue.Equals(postedValue))
{
Text = postedValue;
return true;
}
return false;
}
public virtual void RaisePostDataChangedEvent()
{
OnTextChanged(EventArgs.Empty);
}
protected virtual void OnTextChanged(EventArgs e)
{
if (TextChanged != null)
TextChanged(this,e);
}
protected override void Render(HtmlTextWriter output)
{
output.AddAttribute(HtmlTextWriterAttribute.Type, "text");
output.AddAttribute(HtmlTextWriterAttribute.Value, this.Text);
output.AddAttribute(HtmlTextWriterAttribute.Name, this.UniqueID);
output.RenderBeginTag(HtmlTextWriterTag.Input);
output.RenderEndTag();
}
}
}