自定义控件在事件后不呈现
我只是在玩自定义控件,并且构建了一个看起来像这样的控件:
<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();
}
使用我拥有的代码,所有内容在第一次加载时都呈现良好。我什至有一个与单击时触发的列表项相关联的事件,并且该事件有效。问题是自定义控件的更新没有发生。对于此示例,我尝试禁用用户上次单击的列表项,并确保启用所有其他项。这是控件的代码:
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);
}
}
}
我很确定我的渲染/CreateChildren 过程做得不对。问题是我找不到一个很好的例子来展示如何在需要更新时重新呈现用户控件。有正确的方法吗?
I am just playing with custom controls, and have one built that looks like so:
<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();
}
With the code that I have everything is rendering fine on the first load. I even have a event tied to the list items that fires when clicked, and that works. The problem is updates to the custom control are not taking place. For this example I am trying to disable the listitem the user last clicked, and make sure all others are enabled. Here is the code for the control:
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);
}
}
}
I'm pretty sure its the Rendering / CreateChildren process that I'm not doing right. Problem is I cant find a good example that shows how to rerender your usercontrol when something needs updating. Is there a right way to do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在我看来,
Render()
方法中的所有内容都应该位于CreateChildControls()
方法中。Render
用于覆盖控件输出的实际 HTML。当生成响应流时,它将在生命周期的稍后阶段被调用。CreateChildControls
可以在生命周期中的多个点调用,并且将在第一次需要实例化控件时调用 - 就像在 ViewState 处理期间一样。It seems to me that everything inside of your
Render()
method should be inside yourCreateChildControls()
method.Render
is for overriding the actual HTML that is output by your control. It will be called later in the lifecycle when the response stream is being generated.CreateChildControls
can be called at several points in the lifecycle, and will be called the first time your control needs to be instantiated - like during ViewState handling.