一个简单的例子:
public class CalcComposite:Control
{
TextBox _operand1;
protected override void CreateChildControls()
{
_operand1 = new TextBox();
Controls.Add(_operand1);
}
}
页面:
<cc1:CalcComposite id="tt" runat="server"></cc1:CalcComposite>
<asp:Button id="Button1" runat="server" Text="Button"></asp:Button>情况描述:
在CalcComposite产生的控件的子控件里输入:aaaaaa 然后点击button后,该子控件被清空了,即aaaa不见了。
如果该类实现了INamingContainer的话,点击Button之后,aaaaaa仍然存在,即子控件的值保持住了。问题:
页面Post之后,服务端应该是新建了该页面类的一个对象。该对象的Controls下有这样一个CalcComposite的对象,也是新建的。所以该CalcComposite对象的_operator1应该是在CreateChildControls的时候新建的。我跟踪过该函数,至少在该函数结束,_operand1.Text的值都还是string.Empty;是在什么时候从Post过来的表单里面取得相应的值赋给他的呢?又是通过什么东西来确定他们是相对应的呢?---------------------------------------------------
我不知道我讲明白没有。或者可以告诉我整个提交然后展示的过程。
public class CalcComposite:Control
{
TextBox _operand1;
protected override void CreateChildControls()
{
_operand1 = new TextBox();
Controls.Add(_operand1);
}
}
页面:
<cc1:CalcComposite id="tt" runat="server"></cc1:CalcComposite>
<asp:Button id="Button1" runat="server" Text="Button"></asp:Button>情况描述:
在CalcComposite产生的控件的子控件里输入:aaaaaa 然后点击button后,该子控件被清空了,即aaaa不见了。
如果该类实现了INamingContainer的话,点击Button之后,aaaaaa仍然存在,即子控件的值保持住了。问题:
页面Post之后,服务端应该是新建了该页面类的一个对象。该对象的Controls下有这样一个CalcComposite的对象,也是新建的。所以该CalcComposite对象的_operator1应该是在CreateChildControls的时候新建的。我跟踪过该函数,至少在该函数结束,_operand1.Text的值都还是string.Empty;是在什么时候从Post过来的表单里面取得相应的值赋给他的呢?又是通过什么东西来确定他们是相对应的呢?---------------------------------------------------
我不知道我讲明白没有。或者可以告诉我整个提交然后展示的过程。
不信你可以试试看,如果不实现该接口,子控件的状态无法保持。我用语可以不专业,不知道你能不能听懂我的意思。
protected override void CreateChildControls()
{
_operand1 = new TextBox(); ”
并没有使用任何控件保存其状态,也就是说_operand1只是个临时变量,每次刷新页面当然会新建。请使用容器控件通过ViewState来保存
textbox tbx = new textbox();
if(!page.ispostback)
{
tbx.id = "a";
}
else
{
tbx.id = "b";
}
this.controls.add(tbx);
这样你会发现在第一次提交后,该textbox 的状态也无法保存,原因同你的问的一样
因为你复合控件内部放了一个 TextBox,而TextBox 实现了IPostBackDataHandler接口。
所以在内部比有IPostBackDataHandler.LoadPostData方法该方法用作“加载上一次控件属性页请求的状态,即使控件禁用视图状态,也应在回发间保存控件属性。”我们来看一下TextBox的LoadPostData的实现部分:protected virtual bool LoadPostData(string postDataKey, NameValueCollection postCollection)
{
base.ValidateEvent(postDataKey
string text = this.Text;
string str2 = postCollection[postDataKey];
if (!this.ReadOnly && !text.Equals(str2, StringComparison.Ordinal))
{
this.Text = str2;
return true;
}
return false;
}而传入的postDataKey是什么呢 这里我们就大胆猜测一下它是控件的UniqueID,
为何这么猜测呢,http://msdn2.microsoft.com/zh-cn/library/system.web.ui.ipostbackdatahandler.loadpostdata(VS.80).aspx中参数说明指出出
postDataKey
控件的主要标识符。
所以
当不实现INamingContainer接口时控件内部的字控件无法正确的拥有UniqueID,当然无法正确LoadPostData了
参看:引发自定义控件LoadPostData方法的必要条件