如何在按钮单击时以编程方式添加控件?

时间:2012-11-16 11:05:23

标签: .net dynamic-controls multiview

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

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

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

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

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

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

总而言之,我对使用动态控件缺乏经验,所以任何建议都会受到赞赏。

1 个答案:

答案 0 :(得分: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

Basicaly的工作原理如下:

  • 选择汽车品牌并选择按钮(按钮是我们生成控件的标准) 当然,你也可以用下拉等做逻辑。
  • 在第二个屏幕上,根据您的选择,您有一到两个下拉菜单
  • 如果你有两个下拉,第二个依赖于第一个下拉选项,所以你有依赖和回发的例子

网页代码:

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

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