[英]how to preserve control type between postbacks in asp.net webforms
我想在Webforms中創建一個簡單的表單生成引擎,並且在回發期間無法維護頁面上的控件,用戶可以從DropDownList
選擇控件的類型,如果它是單選按鈕(位於索引3中) ),它將啟用一個TextBox
來定義單選按鈕的GroupName
屬性。我設置了SelectedIndexChanged
來處理txtboxGroupName
的禁用和啟用。
對於用戶添加的每個控件,我想向他們顯示表單中到目前為止發生的事情的預覽。該預覽發生在ID為panel
的Panel
控件中。
問題是在回發中,創建的控件從面板中消失(對於asp.net回發系統,這應該是這樣),而我想保留它們。由於我不知道控件的類型,所以我無法只需將一些id放在viewstate中,例如,可以使用這些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似乎也會忽略控件的狀態,並且不會填充其屬性,我現在該怎么辦?
我建議使用數據綁定來實現“動態”控件。 將“數據模型”與實際控件分開也是一個好主意。 請參見下面的示例。
標記:
<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);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.