我想创建一个可重用的用户控件,允许用户创建和删除标记。
它应该有一个文本框,用户可以在其中输入标记名称,以及一个用于提交标记的按钮。
对标签求和后,它应该动态创建一个带有"X"按钮的标签名称标签,以便为每个输入的标签删除它。
像这样:
[ Textbox ] [Submit]
[X] Tag 1
[X] Tag 2
[X] Tag 3
问题是我无法弄清楚如何使一切正常工作。
选择器.ascx
< markup for the textbox >
< markup for the sumbit button >
<asp:Placeholder runat="server" ID="PHList" />
我正在使用asp:占位符来生成动态控件。
Selector.ascx.cs
我需要跟踪回发之间生成的控件。
我正在使用存储在视图状态中的List<string>
:
private List<string> SelectedTags
{
get
{
return (List<string>) ViewState["SelectedTags"];
}
set { ViewState["SelectedTags"] = value; }
}
当我单击提交按钮时,我将一个新标记添加到 SelectedTags 列表中,并调用 RefreshPlaceholder 函数:
void RefreshPlaceholder()
{
PHList.Controls.Clear();
foreach(var x in SelectedTags)
{
// generate a label and the "X" button, wiring it with a lambda
}
}
当我单击提交按钮时,会正确生成一个新的(按钮、标签(对并在回发后显示。
但是,当我单击任何生成的"X"按钮时,我收到错误,因为动态生成的按钮触发的单击事件无法再找到发送者按钮,因为它尚未生成。
如果我尝试在 OnLoad 中生成按钮,则会出现同样的问题,因为回发事件发生在 Page.Load 之前。
如果我尝试在 OnInit 中生成按钮,则视图状态尚未更新,因此生成的列表将过时,因为 SelectedTags 视图状态列表尚未更新。
我似乎找不到使一切按预期工作的解决方案。我做错了什么?
在 OnInit 方法上声明一个 Button 类型的列表;然后在 RefreshPlaceHolder 中检索并循环访问选定的标记并将它们添加到 List
protected override void OnInit(EventArgs e)
{
List<Button> listButtons ;
base.OnInit(e);
}
void RefreshPlaceholder()
{
listButtons = new List<Button>();
PHList.Controls.Clear();
foreach(var x in SelectedTags)
{
Button b = new Button();
b.Text=x;
listButtons.add(b);
// generate a label and the "X" button, wiring it with a lambda
}
}