我想在webforms中创建一个简单的表单生成引擎,我在回发期间在页面上维护控件时遇到问题。用户可以选择控件的类型DropDownList
,如果是收音机按钮(在索引3中),它将启用TextBox
定义单选按钮的GroupName
属性。我已设置SelectedIndexChanged
来处理禁用和启用{ {1}}。
对于用户添加的每个控件,我想向他们展示目前在表单中发生的事情的预览。预览发生在txtboxGroupName
控件中,其ID为Panel
。< / p>
问题是在回发中,创建的控件从面板中消失(这是应该使用asp.net回发系统的方式)并且我想保留它们。因为我不知道控件的类型,我不能只在视图状态中放置一些ID,例如预先设置带有这些ID的控件
我试图做这样的事情,但它不起作用:
这是背后的代码:
panel
这是我的aspx页面
public int NumberOfControls
{
get { return (int)ViewState["NumOfControls"]; }
set { ViewState["NumOfControls"] = value; }
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
this.NumberOfControls = 0;
else
this.CreateControls();
}
private void CreateControls()
{
for (int counter = 0; counter < this.NumberOfControls; counter++)
{
Control temp = new Control();
temp.ID = "control_id_" + counter.ToString();
panel.Controls.Add(temp);
}
}
protected void ddlControlType_SelectedIndexChanged(object sender, EventArgs e)
{
switch (ddlControlType.SelectedIndex)
{
case 0:
case 2:
txtboxText.Enabled = true;
txtboxGroupName.Enabled = false;
break;
case 1:
txtboxText.Enabled = false;
txtboxGroupName.Enabled = false;
break;
case 3:
txtboxText.Enabled = true;
txtboxGroupName.Enabled = true;
break;
}
}
protected void btnAddControl_Click(object sender, EventArgs e)
{
Control tempControl = null;
switch (ddlControlType.SelectedIndex)
{
case 0:
tempControl = new Label();
((Label)tempControl).Text = txtboxText.Text;
break;
case 1:
tempControl = new TextBox();
break;
case 2:
tempControl = new CheckBox();
((CheckBox)tempControl).Text = txtboxText.Text;
break;
case 3:
tempControl = new RadioButton();
((RadioButton)tempControl).Text = txtboxText.Text;
((RadioButton)tempControl).GroupName = txtboxGroupName.Text;
break;
}
tempControl.ID = "control_id_" + this.NumberOfControls.ToString();
panel.Controls.Add(tempControl);
this.NumberOfControls++;
}
<div class="main-wrapper">
<form dir="rtl" id="form" runat="server">
<label>Desired Control : </label>
<asp:DropDownList AutoPostBack="true" ID="ddlControlType" OnSelectedIndexChanged="ddlControlType_SelectedIndexChanged" runat="server">
<asp:ListItem Text="label"></asp:ListItem>
<asp:ListItem Text="text box"></asp:ListItem>
<asp:ListItem Text="check box"></asp:ListItem>
<asp:ListItem Text="radio button"></asp:ListItem>
</asp:DropDownList>
<br /><br />
<label class="label">control's text : </label>
<asp:TextBox ID="txtboxText" runat="server" CssClass="txtbox"></asp:TextBox>
<label class="label">group name (only for radio button)</label>
<asp:TextBox Enabled="false" ID="txtboxGroupName" runat="server" CssClass="txtbox"></asp:TextBox>
<br /><br />
<asp:Button ID="btnAddControl" CssClass="btn" Text="add to form" OnClick="btnAddControl_Click" runat="server" />
<hr />
<h1>form preview</h1>
<asp:Panel ID="panel" runat="server">
</asp:Panel>
</form>
</div>
是触发添加控件的按钮。此方法创建的控件不会保留在回发中(无论是另一个按钮单击还是更改下拉列表的选定索引)
此代码的问题是面板控件中没有添加任何内容(我认为这是因为我使用的是通用的btnAddControl
类型,但是我不知道类型)
我该如何保留这些控件?
更新
我重新创建了我的代码,但它仍然不起作用:
Control
此代码实际上会在页面加载时添加控件,但即使使用相同的id,viewstate似乎也会忽略控件的状态,并且不会填充其属性 我现在该怎么办?
答案 0 :(得分:0)
我建议使用数据绑定来实现&#34; dynamic&#34;控制。另外,分离数据模型&#34;是个好主意。从实际控制。见下面的例子。
标记:
<asp:Repeater ID="rptControls" runat="server" OnItemDataBound="rptControls_ItemDataBound" >
<ItemTemplate>
<asp:Label runat="server" Visible="false" ID="lbl" />
<asp:CheckBox runat="server" Visible="false" ID="chx" />
</ItemTemplate>
</asp:Repeater>
<asp:TextBox ID="txtText" runat="server" />
<asp:Button ID="btnAddLabel" runat="server" OnClick="btnAddLabel_Click" Text="Add label" />
<asp:Button ID="btnAddCheckBox" runat="server" OnClick="btnAddCheckBox_Click" Text="Add check box" />
数据模型:
[Serializable]
public abstract class ControlDescriptor {
public abstract void SetupControl(ControlCollection controls);
}
[Serializable]
public class LabelDescriptor : ControlDescriptor {
public string Text { get; set; }
public override void SetupControl(ControlCollection controls) {
var cotrol = controls.OfType<Label>().First(c => c.ID == "lbl");
cotrol.Visible = true;
cotrol.Text = Text;
}
}
[Serializable]
public class CheckBoxDescriptor : ControlDescriptor {
public string Text { get; set; }
public override void SetupControl(ControlCollection controls) {
var cotrol = controls.OfType<CheckBox>().First(c => c.ID == "chx");
cotrol.Visible = true;
cotrol.Text = Text;
}
}
代码背后:
protected void Page_Load(object sender, EventArgs e) {
Rebind();
}
protected IList<ControlDescriptor> Descriptors {
get {
var result = (IList<ControlDescriptor>)ViewState["Descriptors"];
if (result == null) {
result = new List<ControlDescriptor>();
ViewState["Descriptors"] = result;
}
return result;
}
}
protected void Rebind() {
rptControls.DataSource = Descriptors;
rptControls.DataBind();
}
protected void btnAddCheckBox_Click(object sender, EventArgs e) {
Descriptors.Add(new CheckBoxDescriptor { Text = txtText.Text });
Rebind();
}
protected void btnAddLabel_Click(object sender, EventArgs e) {
Descriptors.Add(new LabelDescriptor { Text = txtText.Text });
Rebind();
}
protected void rptControls_ItemDataBound(object sender, RepeaterItemEventArgs e) {
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem) {
var descriptor = (ControlDescriptor)e.Item.DataItem;
descriptor.SetupControl(e.Item.Controls);
}
}