【发布时间】:2015-11-16 07:42:39
【问题描述】:
我想在 web 表单中创建一个简单的表单生成引擎,但在回发期间维护页面上的控件时遇到了麻烦。用户可以选择控件表单的类型为 DropDownList,如果它是单选按钮(在索引 3) 中,它将启用一个 TextBox,它定义了单选按钮的 GroupName 属性。我设置了一个 SelectedIndexChanged 来处理 txtboxGroupName 的禁用和启用。
对于用户添加的每个控件,我想向他们展示迄今为止在表单中发生的事情的预览。预览发生在 ID 为 panel 的 Panel 控件中。
问题是,在回发中,创建的控件从面板中消失(这应该是 asp.net 回发系统的方式),我想保留它们。因为我不知道控件的类型,所以我不能只在视图状态中放置一些 id,例如用这些 id 来保存控件
我试图做这样的事情,但它不起作用:
这是后面的代码:
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++;
}
这是我的 aspx 页面
<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 类型,但同样,我不知道类型)
如何保留这些控件?
更新:
我为这个重新创建了我的代码,但它仍然无法工作:
public Dictionary<string, Type> ControlTypes
{
get { return (Dictionary<string, Type>)Session["ControlTypes"]; }
set { Session["ControlTypes"] = value; }
}
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;
ControlTypes = new Dictionary<string, Type>();
}
else
this.CreateControls();
}
private void CreateControls()
{
for (int counter = 0; counter < this.NumberOfControls; counter++)
{
string controlId = "control_id_" + counter.ToString();
Type controlType = ControlTypes[controlId];
ProperyInfo[] properties = controlType.GetProperties();
Object controlObject = Activator.CreateInstance(controlType);
foreach (var propery in properties)
{
If (propery.Name == "ID")
Property.SetValue(controlObject, controlId, null);
}
panel.Controls.Add(controlObject as Control)
}
}
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;
}
string controlId = "control_id_" + this.NumberOfControls.ToString();
tempControl.ID = controlId;
panel.Controls.Add(tempControl);
this.NumberOfControls++;
ControlTypes.Add(controlId, tempControl.GetType());
}
此代码实际上在页面加载时添加了控件,但即使使用相同的 id,viewstate 似乎也忽略了控件的状态并且不会填充其属性 我现在该怎么办?
【问题讨论】:
-
我不知道你为什么需要
else this.CreateControls(); }? -
如果是回发,那么我应该再次在页面加载中创建控件,我确信这部分。我遇到问题的部分是 CreateControl 本身以及其中的内容
-
您提供的代码是网页控制的代码吗?还是网页?你能提供复杂的样本吗?
-
这是网页背后的代码 这是我正在使用的确切代码
-
还提供 aspx 标记