簡體   English   中英

如何在ASP.NET Web表單中保留回發之間的控件類型

[英]how to preserve control type between postbacks in asp.net webforms

我想在Webforms中創建一個簡單的表單生成引擎,並且在回發期間無法維護頁面上的控件,用戶可以從DropDownList選擇控件的類型,如果它是單選按鈕(位於索引3中) ),它將啟用一個TextBox來定義單選按鈕的GroupName屬性。我設置了SelectedIndexChanged來處理txtboxGroupName的禁用和啟用。

對於用戶添加的每個控件,我想向他們顯示表單中到目前為止發生的事情的預覽。該預覽發生在ID為panelPanel控件中。

問題是在回發中,創建的控件從面板中消失(對於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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM