Как да добавяте контроли програмно при натискане на бутон?

Имам формуляр за уебсайт (c#), който се намира в контрола с много изгледи. Контролът на muliview има 4 стъпки, така че първите 3 стъпки събират информация и ако са валидни, преминават към следващия изглед при натискане на бутон.

Искам динамично да създам формуляра въз основа на предишни отговори, но от това, което прочетох досега, малко не съм сигурен как да направя това.

Например на стъпка 1 потребителят попълва някои контроли на текстовото поле и щраква върху изпращане.

Въз основа на данните, подадени в панел 1, следващият панел трябва динамично да създаде редица контроли - някои етикети, някои текстови полета.

Тъй като това кликване е както след init, така и след page_load, не съм сигурен как ще работи това.

Разбира се, бих могъл да създам всички контроли за етикет/текстово поле отпред и да ги деактивирам, ако е необходимо, но това изглежда е доста лошо използване на ресурса.

В крайна сметка, нямам опит в работата с динамични контроли, така че всеки съвет ще бъде оценен.


person dotnetnoob    schedule 16.11.2012    source източник
comment
Какво правите с данните от втория панел, има ли бутони, обратно изпращане и т.н.? Ако създадете контроли след OnInit, те все още се създават, но данните за обратно изпращане няма да бъдат автоматично зададени. Така че, ако извикате обратно изпращане на втори панел и имате нужда от данни от тези динамични контроли, трябва да получите тези данни в OnInit от Request.Forms[dynamicControlClientId] или може би да съхраните това във ViewState. Друг проблем е дали трябва да виждате динамични контроли след връщане, така че трябва да съхранявате информация във втория панел как да създадете контроли при връщане (условия от първия панел).   -  person pawciu    schedule 16.11.2012
comment
Да, ще има допълнителни връщания. Във всички мултиизгледи има 4 стъпки, така че първите 3 ще изпращат обратно, когато преминат към следващата стъпка.   -  person dotnetnoob    schedule 16.11.2012


Отговори (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

Данните за този пример изглеждат така

Марка Цвят на двигателя Цена
VW, 1.2, Черен, 72 000
VW, 1.2, Бял, 70 000
VW, 1.6 TDI, Червен, 79 500
VW, 1.6 TDI, Бял, 78 800
Форд, 1.6, Черен, 57 600
Форд, 1.6, Зелен, 57 100
Форд, 2.0 TDCi, Черен, 87 300
Форд, 2.0 TDCi, Бяло, 86 600

По принцип това работи по следния начин:

  • Изберете марка автомобил и изберете бутон (бутонът е нашият критерий за генериране на контроли) Разбира се, можете също да правите логика с падащи менюта и т.н.
  • На втория екран имате едно или две падащи менюта според вашия избор
  • Ако имате две падащи менюта, второто зависи от избора на първото падащо меню, така че имате пример за зависимост и обратно изпращане

Код на страницата:

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

Ако имате допълнителни въпроси, ще се радвам да помогна

person pawciu    schedule 17.11.2012