【问题标题】:how to preserve control type between postbacks in asp.net webforms如何在asp.net webforms中的回发之间保留控件类型
【发布时间】:2015-11-16 07:42:39
【问题描述】:

我想在 web 表单中创建一个简单的表单生成引擎,但在回发期间维护页面上的控件时遇到了麻烦。用户可以选择控件表单的类型为 DropDownList,如果它是单选按钮(在索引 3) 中,它将启用一个 TextBox,它定义了单选按钮的 GroupName 属性。我设置了一个 SelectedIndexChanged 来处理 txtboxGroupName 的禁用和启用。

对于用户添加的每个控件,我想向他们展示迄今为止在表单中发生的事情的预览。预览发生在 ID 为 panelPanel 控件中。

问题是,在回发中,创建的控件从面板中消失(这应该是 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 标记

标签: c# asp.net


【解决方案1】:

我建议使用数据绑定来实现“动态”控件。将“数据模型”与实际控件分开也是一个好主意。请参见下面的示例。

标记:

<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);
  }
}

【讨论】:

  • 一段不错的代码,但我想实际生成控件,而不是让它们可见和不可见
猜你喜欢
  • 1970-01-01
  • 2010-10-04
  • 2010-09-12
  • 1970-01-01
  • 2012-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多