【问题标题】:How to add controls programatically on button click?如何在按钮单击时以编程方式添加控件?
【发布时间】:2012-11-16 11:05:23
【问题描述】:

我有一个位于多视图控件内的网站表单 (c#)。 muliview 控件有 4 个步骤,因此前 3 个步骤收集信息,如果有效,则在按钮单击时移动到下一个视图。

我想根据以前的答案动态构建表单,但从我目前阅读的内容来看,我有点不确定如何实现这一点。

例如,在第 1 步中,用户完成了一些文本框控件并单击提交。

根据面板1提交的数据,下一个面板需要动态创建一些控件——一些标签,一些文本框。

由于此点击是在 init 和 page_load 之后进行的,我不确定这将如何工作。

当然,我可以预先创建所有标签/文本框控件并根据需要禁用它们,但这似乎对资源的使用非常糟糕。

归根结底,我在使用动态控件方面缺乏经验,因此不胜感激。

【问题讨论】:

  • 你对第二个面板的数据做了什么,有没有按钮,回发等?如果您在 OnInit 之后创建控件,它们仍然会创建,但不会自动设置回发数据。因此,如果您在第二个面板上调用回发并且您需要来自这些动态控件的数据,您需要从 Request.Forms[dynamicControlClientId] 在 OnInit 中获取此数据,或者将其存储在 ViewState 中。另一个问题是您是否需要在回发后查看动态控件,因此您必须在第二个面板上存储如何在回发上创建控件的信息(来自第一个面板的条件)。
  • 是的,会有更多回发。在所有多视图中都有 4 个步骤,因此前 3 个步骤将在他们进入下一步时回发。

标签: .net dynamic-controls multiview


【解决方案1】:

好的,下面我粘贴了工作示例。 需要注意的事项:

  • 为了避免错误

Message=Failed to load viewstate. The control tree into which viewstate is being loaded must match the control tree that was used to save viewstate during the previous request. For example, when adding controls dynamically, the controls added during a post-back must match the type and position of the controls added during the initial request. Source=System.Web ErrorCode=-2147467259

在动态控件上设置此属性

EnableViewState = false

此示例的数据如下所示

品牌引擎色彩成本
大众,1.2,黑色,72 000
大众,1.2,白色,70 000
大众,1.6 TDI,红色,79 500
大众,1.6 TDI,白色,78 800
福特,1.6,黑色,57 600
福特,1.6,格林,57 100
福特,2.0 TDCi,黑色,87 300
福特,2.0 TDCi,白色,86 600

基本上是这样工作的:

  • 选择汽车品牌并选择按钮(按钮是我们生成g控件的标准) 当然,您也可以使用下拉列表等进行逻辑处理。
  • 在第二个屏幕上,根据您的选择,您有一个或两个下拉菜单
  • 如果您有两个下拉菜单,第二个取决于第一个下拉菜单的选择,因此您有依赖和回发的示例

页面代码:

<form id="form1" runat="server">
<div>
<asp:MultiView ID="mvPanels" runat="server">
    <asp:View ID="vPanel1" runat="server">
        <table>
            <tbody>
                <tr>
                    <td>Pick car</td>
                    <td><asp:DropDownList ID="ddlBrand" runat="server" /></td>
                    <td><asp:Button ID="btnPanel1Next" Text="Next" runat="server" 
                            onclick="btnPanel1Next_Click" /></td>
                    <td><asp:Button ID="btnPanel1NextEngineOnly" Text="Next (pick engine only)" runat="server" 
                            onclick="btnPanel1NextEngineOnly_Click" /></td>
                </tr>
            </tbody>
        </table>
    </asp:View>
    <asp:View ID="vPanel2" runat="server">
        <%--<table>
            <tbody>
                <tr>
                    <td>Pick engine</td>
                    <td><asp:DropDownList ID="ddlEngine" AutoPostBack="true" runat="server" 
                            onselectedindexchanged="ddlEngine_SelectedIndexChanged" /></td>
                    <td><asp:DropDownList ID="ddlColor" AutoPostBack="true" runat="server" 
                            onselectedindexchanged="ddlColor_SelectedIndexChanged" /></td>
                    <td><asp:Button ID="btnPanel2Prev" Text="Prev" runat="server" 
                            onclick="btnPanel2Prev_Click" /><asp:Button ID="btnPanel2Next" Text="Next" 
                            runat="server" Enabled="False" onclick="btnPanel2Next_Click" /></td>
                </tr>
            </tbody>
        </table>--%>
    </asp:View>
    <asp:View ID="vPanel3" runat="server">
        <table>
            <tbody>
                <tr>
                    <td><asp:Label ID="lblResult" runat="server" /></td>
                    <td><asp:Button ID="btnPanel3Prev" Text="Prev" runat="server" 
                            onclick="btnPanel3Prev_Click" /><asp:Button ID="btnPanel3Finish" 
                            Text="Confirm" runat="server" onclick="btnPanel3Finish_Click" /></td>
                </tr>
            </tbody>
        </table>
    </asp:View>
</asp:MultiView>
</div>
</form>

后面的代码:

public partial class Default : System.Web.UI.Page
{
    public class CarConfiguration
    {
        public string Brand { get; set; }
        public string Engine { get; set; }
        public PaintColor Paint { get; set; }
        public string Cost { get; set; }
    }

    [Serializable]
    public class CarConfigurationFilter
    {
        public string Brand { get; set; }
        public string Engine { get; set; }
        public PaintColor? Paint { get; set; }
        public bool EngineOnly { get; set; }
    }

    public enum PaintColor
    {
        Black,
        Red,
        White,
        Green,
    }

    public List<CarConfiguration> availableCars = new List<CarConfiguration>
    {
        new CarConfiguration{
            Brand = "VW",
            Engine = "1.2",
            Paint = PaintColor.Black,
            Cost = "72 000",
        },
        new CarConfiguration{
            Brand = "VW",
            Engine = "1.2",
            Paint = PaintColor.White,
            Cost = "70 000",
        },
        new CarConfiguration{
            Brand = "VW",
            Engine = "1.6 TDI",
            Paint = PaintColor.Red,
            Cost = "79 500"
        },
        new CarConfiguration{
            Brand = "VW",
            Engine = "1.6 TDI",
            Paint = PaintColor.White,
            Cost = "78 800",
        },
        new CarConfiguration{
            Brand = "Ford",
            Engine = "1.6",
            Paint = PaintColor.Black,
            Cost = "57 600"
        },
        new CarConfiguration{
            Brand = "Ford",
            Engine = "1.6",
            Paint = PaintColor.Green,
            Cost = "57 100"
        },
        new CarConfiguration{
            Brand = "Ford",
            Engine = "2.0 TDCi",
            Paint = PaintColor.Black,
            Cost = "87 300"
        },
        new CarConfiguration{
            Brand = "Ford",
            Engine = "2.0 TDCi",
            Paint = PaintColor.White,
            Cost = "86 600"
        },
    };

    CarConfigurationFilter filter
    {
        get { return (CarConfigurationFilter)ViewState["Filter"]; }
        set { ViewState["Filter"] = value; }
    }

    //If you have multiview in control you need to create this in event before event PageLoad like  LoadViewState, LoadControlState, LoadControlState
    protected override void OnPreLoad(EventArgs e)
    {
        if (IsPostBack && mvPanels.ActiveViewIndex == 1)
        {
            CreateControlsOnPanel2(true, !filter.EngineOnly);
        }
        base.OnPreLoad(e);
    }

    protected override void OnLoad(EventArgs e)
    {
        if (!IsPostBack)
        {
            ddlBrand.DataSource = availableCars.Select(x => x.Brand).Distinct();
            ddlBrand.DataBind();
            filter = new CarConfigurationFilter();
            mvPanels.ActiveViewIndex = 0;
        }
        base.OnLoad(e);
    }

    protected void btnPanel1Next_Click(object sender, EventArgs e)
    {
        filter.Brand = ddlBrand.SelectedValue;
        filter.EngineOnly = false;

        CreateControlsOnPanel2(true, true);

        mvPanels.ActiveViewIndex++; 
    }

    protected void btnPanel1NextEngineOnly_Click(object sender, EventArgs e)
    {
        filter.Brand = ddlBrand.SelectedValue;
        filter.EngineOnly = true;
        CreateControlsOnPanel2(true, false);

        mvPanels.ActiveViewIndex++; 
    }

    void CreateControlsOnPanel2(bool enginePickerEnabled, bool colorPickerEnabled)
    {
        var btnPanel2Prev = new Button();
        btnPanel2Prev.ID = "btnPanel1Prev";
        btnPanel2Prev.EnableViewState = false;    
        btnPanel2Prev.Text = "Prev";
        btnPanel2Prev.Click += btnPanel2Prev_Click;

        var btnPanel2Next = new Button();
        btnPanel2Next.ID="btnPanel2Next";
        btnPanel2Next.Text = "Next";
        btnPanel2Next.EnableViewState = false;
        btnPanel2Next.Enabled = false;
        btnPanel2Next.Click += btnPanel2Next_Click;


        if (enginePickerEnabled)
        {
            var ddlEngine = new DropDownList();
            ddlEngine.ID = "ddlEngine";
            ddlEngine.AutoPostBack = true;
            ddlEngine.EnableViewState = false;

            var engines = availableCars.Where(x => x.Brand == filter.Brand).Select(found => found.Engine).Distinct().ToList();
            engines.Insert(0, String.Empty);
            ddlEngine.DataSource = engines;
            ddlEngine.DataBind();
            if (!String.IsNullOrEmpty(filter.Engine))
            {
                ddlEngine.SelectedValue = filter.Engine;
                if (!colorPickerEnabled)
                    btnPanel2Next.Enabled = true;
            }
            else
                ddlEngine.SelectedIndex = 0;
            ddlEngine.SelectedIndexChanged += ddlEngine_SelectedIndexChanged;
            vPanel2.Controls.Add(ddlEngine);
        }
        //remember to add ID to all dynamic controls or there might be an error on postback
        if (colorPickerEnabled)
        {
            var ddlColor = new DropDownList();
            ddlColor.ID = "ddlColor";
            ddlColor.AutoPostBack = true;
            ddlColor.EnableViewState = false;
            ddlColor.SelectedIndexChanged += ddlColor_SelectedIndexChanged;
            vPanel2.Controls.Add(ddlColor);

            if (!String.IsNullOrEmpty(filter.Engine))
            {
                var colors = availableCars.Where(x => x.Brand == filter.Brand && x.Engine == filter.Engine).Select(found => found.Paint.ToString()).Distinct().ToList();
                colors.Insert(0, String.Empty);
                ddlColor.DataSource = colors;
                if (filter.Paint.HasValue)
                {
                    ddlColor.SelectedValue = filter.Paint.Value.ToString();
                    btnPanel2Next.Enabled = true;
                }

            }
            else
            {
                ddlColor.DataSource = null;
                ddlColor.SelectedIndex = 0;
            }
            ddlColor.DataBind();
        }

        vPanel2.Controls.Add(btnPanel2Prev);
        vPanel2.Controls.Add(btnPanel2Next);
    }

    protected void ddlEngine_SelectedIndexChanged(object sender, EventArgs e)
    {
        var ddlEngine = sender as DropDownList;
        var btnPanel2Next = (Button)vPanel2.FindControl("btnPanel2Next");

        if (!String.IsNullOrEmpty(ddlEngine.SelectedValue))
        {
            filter.Engine = ddlEngine.SelectedValue;
            var colors = availableCars.Where(x => x.Brand == filter.Brand && x.Engine == filter.Engine).Select(found => found.Paint.ToString()).Distinct().ToList();
            colors.Insert(0, String.Empty);
            filter.Paint = null;

            var ddlColor = (DropDownList)vPanel2.FindControl("ddlColor");
            if (ddlColor != null)
            {
                ddlColor.DataSource = colors;
                ddlColor.DataBind();
                ddlColor.SelectedIndex = 0;

                btnPanel2Next.Enabled = false;
            }
            else
                btnPanel2Next.Enabled = true;
        }
        else
        {
            var ddlColor = (DropDownList)vPanel2.FindControl("ddlColor");
            if (ddlColor != null)
            {
                ddlColor.Items.Clear();
                ddlColor.SelectedIndex = -1;
            }
            filter.Engine = null;
            btnPanel2Next.Enabled = false;
        }
    }

    protected void ddlColor_SelectedIndexChanged(object sender, EventArgs e)
    {
        var ddlColor = (DropDownList)vPanel2.FindControl("ddlColor");
        var btnPanel2Next = (Button)vPanel2.FindControl("btnPanel2Next");

        if (!String.IsNullOrEmpty(ddlColor.SelectedValue))
        {
            filter.Paint = (PaintColor)Enum.Parse(typeof(PaintColor), ddlColor.SelectedValue);
            btnPanel2Next.Enabled = true;
        }
        else
        {
            filter.Paint = null;
            btnPanel2Next.Enabled = false;
        }
    }

    protected void btnPanel2Prev_Click(object sender, EventArgs e)
    {
        filter.Engine = null;
        filter.Paint = null;
        mvPanels.ActiveViewIndex--;
    }

    protected void btnPanel2Next_Click(object sender, EventArgs e)
    {
        mvPanels.ActiveViewIndex++;

        var selectedConfiguration = availableCars.Where(x => x.Brand == filter.Brand && x.Engine == filter.Engine
        && (!filter.Paint.HasValue || x.Paint == filter.Paint)).Distinct().FirstOrDefault();
        if (selectedConfiguration != null)
            lblResult.Text = String.Format("You have selected {0} {1} {2} for {3} PLN", selectedConfiguration.Brand,
                selectedConfiguration.Engine, selectedConfiguration.Paint, selectedConfiguration.Cost);
    }

    protected void btnPanel3Prev_Click(object sender, EventArgs e)
    {
        mvPanels.ActiveViewIndex--;
        CreateControlsOnPanel2(true, !filter.EngineOnly);

    }

    protected void btnPanel3Finish_Click(object sender, EventArgs e)
    {
    }
}

如果您有任何其他问题,我很乐意为您提供帮助

【讨论】:

    猜你喜欢
    • 2013-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-09
    • 1970-01-01
    • 1970-01-01
    • 2021-05-31
    • 2017-06-17
    相关资源
    最近更新 更多