我只是在玩自定义控件,并且有一个看起来像这样的内置:
<cc:Test ID="jqTestTest01" runat="server" OnTestClick="jqTestTest01_TestClick">
<TestItems>
<asp:ListItem Text="Tab One" Value="1" Selected="True" />
<asp:ListItem Text="Tab Two" Value="2" />
<asp:ListItem Text="Tab Three" Value="3" />
<asp:ListItem Text="Tab Four" Value="4" />
<asp:ListItem Text="Tab Five" Value="5" />
</TestItems>
<ContentTemplate>
<asp:Label ID="lblTestTest01" runat="server" Text="None" />
</ContentTemplate>
</cc:Test>
protected void jqTestTest01_TestClick(object sender, EventArgs e)
{
lblTestTest01.Text = "Click Event! " + DateTime.Now.ToLongTimeString();
}
使用我拥有的代码,第一次加载时一切正常。我甚至有一个事件与单击时触发的列表项相关联,这是有效的。问题是没有发生自定义控件的更新。对于此示例,我尝试禁用用户上次单击的listitem,并确保已启用所有其他项目。以下是控件的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI.WebControls;
using System.Web.UI;
using System.ComponentModel;
namespace MyControls.jqTest
{
[ParseChildren(true), PersistChildren(false)]
public class Test : WebControl, INamingContainer
{
[ParseChildren(true, "Items")]
public class iTestItems
{
private ListItemCollection _Items;
[DefaultValue((string)null), MergableProperty(false), PersistenceMode(PersistenceMode.InnerDefaultProperty)]
public virtual ListItemCollection Items
{
get
{
if (_Items == null)
_Items = new ListItemCollection();
return _Items;
}
}
}
private iTestItems _TestItems = null;
private ITemplate _ContentTemplate = null;
public event EventHandler TestClick = null;
[PersistenceMode(PersistenceMode.InnerProperty),
TemplateContainer(typeof(iTestItems)),
TemplateInstance(TemplateInstance.Single)]
public iTestItems TestItems
{
get { return _TestItems; }
set { _TestItems = value; }
}
[PersistenceMode(PersistenceMode.InnerProperty),
TemplateContainer(typeof(TemplateControl)),
TemplateInstance(TemplateInstance.Single)]
public ITemplate ContentTemplate
{
get { return _ContentTemplate; }
set { _ContentTemplate = value; }
}
protected override void CreateChildControls()
{
Controls.Clear();
Control BtnList = new Control();
Controls.Add(BtnList);
Control Content = new Control();
ContentTemplate.InstantiateIn(Content);
Controls.Add(Content);
}
void Btn_Click(object sender, EventArgs e)
{
Button Btn = (Button)sender;
foreach (ListItem i in _TestItems.Items)
i.Selected = (i.Text == Btn.Text) ? false : true;
if (TestClick != null)
TestClick(sender, e);
}
protected override void Render(HtmlTextWriter writer)
{
Control BtnList = Controls[0];
BtnList.Controls.Clear();
foreach (ListItem i in _TestItems.Items)
{
Button Btn = new Button();
Btn.Text = i.Text;
Btn.Enabled = i.Selected ? false : true;
Btn.Click += new EventHandler(Btn_Click);
BtnList.Controls.Add(Btn);
}
base.Render(writer);
}
}
}
我很确定它的Rendering / CreateChildren进程我做得不对。问题是我无法找到一个很好的例子,展示了在需要更新时如何重新呈现用户控件。有没有正确的方法来做到这一点?
答案 0 :(得分:1)
在我看来,Render()
方法中的所有内容都应该在CreateChildControls()
方法中。
Render
用于覆盖控件输出的实际HTML。它将在生成响应流的生命周期中稍后调用。
CreateChildControls
可以在生命周期的几个点调用,并且在第一次需要实例化控件时调用 - 比如在ViewState处理期间。