0

I have this code which adds a x number of views to a Multiview control. The Multiview control exist on the page with only one view. on page init I create x number of views with a GridView control added to each of these views when I come to loop through to find which one I want to show the Multiview control says it has only 1 view.

    protected void variantRepeat_ItemCommand(object source, RepeaterCommandEventArgs e)
    {
        if (e.CommandSource.GetType() == typeof(LinkButton))
        {
            string theID = ((LinkButton)e.CommandSource).CommandArgument.ToString();
            ViewCollection views = prodView.Views; //this has only 1 view the one that has been added on the source view of the .aspx page
            foreach (View toDisplay in views)
            {
                if (toDisplay.ID == theID)
                    prodView.SetActiveView(toDisplay);
            }
        }

    }

The code above loops to find the view and display it. Why do all the views disappear, I've stepped through and at init and after it has finished processing database queries it has x number of views > the 1 in source view.

Why does this control "lose" the views?

Init code:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (Request.QueryString == null || Request.QueryString.Count < 1)
            Response.Redirect(Server.MapPath("~/Packages/"));
        if (!Page.IsPostBack)
        {
            if (Request.QueryString["id"].ToString() == string.Empty)
                Response.Redirect(Server.MapPath("~/Packages/"));
            var id = Server.HtmlEncode(Request.QueryString["id"].ToString());
            Guid packID = Guid.Parse(id);
            using (var context = new GaleEntities())
            {
                var thePackage = context.PackageEnts.First(p => p.packageID == packID);
                var theVariants = thePackage.Variants;
                var mydatasource = new List<PackageEnt> { thePackage };
                var myVariantDataSource = new List<Variant>();
                foreach (Variant single in theVariants)
                {
                    myVariantDataSource.Add(single);
                }
                packageForm.DataSource = mydatasource;
                variantRepeat.DataSource = myVariantDataSource;
                RenderProductGridviews(theVariants);
                prodView.SetActiveView(prodView.Views[0]);
            }
            packageForm.DataBind();
            variantRepeat.DataBind();
            Page.DataBind();
        }
    }

    protected void RenderProductGridviews(System.Data.Objects.DataClasses.EntityCollection<Variant> variantCol)
    {
        foreach (Variant packVar in variantCol)
        {

            View newView = new View();

            GridView prodGrid = new GridView();
            var myProdDataSource = new List<vw_VariantProduct>();             
            using (var context = new GaleEntities())
            {
                var singleProd1 = context.vw_VariantProduct.Where(vp => vp.variantID == packVar.variantID);
                foreach (vw_VariantProduct extProd in singleProd1)
                {
                    myProdDataSource.Add(extProd);
                }
            }
            prodGrid.DataSource = myProdDataSource;

            BoundField _column = new BoundField();
            _column.DataField = "product_title";
            _column.HeaderText = "Product";
            prodGrid.Columns.Add(_column);

            _column = new BoundField();
            _column.DataField = "product_title";
            _column.HeaderText = "Product";
            prodGrid.Columns.Add(_column);

            _column = new BoundField();
            _column.DataField = "product_desc";
            _column.HeaderText = "Description";
            prodGrid.Columns.Add(_column);

            _column = new BoundField();
            _column.DataField = "product_time";
            _column.HeaderText = "Time (mins)";
            prodGrid.Columns.Add(_column);

            _column = new BoundField();
            _column.DataField = "quantity";
            _column.HeaderText = "Quantity";
            prodGrid.Columns.Add(_column);

            prodGrid.DataBind();
            newView.ID = packVar.variantID.ToString();
            newView.Controls.Add(prodGrid);
            prodView.Views.Add(newView);
        }
    }
Callum Linington
  • 14,213
  • 12
  • 75
  • 154

2 Answers2

3

Now, as usual almost all questions with the dynamic controls in ASP.Net words share the same common problem...

You need to create the dynamic controls on every post, you are only creating them the first time the page is loaded. Follow this simple rules:

  • Dynamic controls should be created in the PreInit event when you are not working with a master page, if you are, then create the controls in the Init event
  • Avoid setting properties that can be changed in each post in these events because when the view state is applied (in a post event) the properties will be overridden
  • Dynamic controls must be created every time the page is posted, avoid this if(!this.IsPostBack) this.CreatemyDynamicControls();
  • When you create the controls in the PreInit or Init events, their states will be automatically set in a post event, which means in the LoadComplete event your controls will contain their state back even when you create them again in each post and even when you did not explicitly set their state. Note this behavior is different when you are dealing with controls created at design time, in that case, the event where the state has been set is the Load event
  • Event subscription should occur before the PageLoadComplete or they will not be raised

I have posted several answers about dynamic controls:

https://stackoverflow.com/a/11127064/1268570

https://stackoverflow.com/a/11167765/1268570

Click events on Array of buttons

Button array disappears after click event

Dynamically create an ImageButton

This piece of code creates dynamic controls on-demand, and each control keeps its state on each post

public partial class DynamicControlsOnDemand : System.Web.UI.Page
{
    public int NumberOfControls
    {
        get
        {
            if (this.ViewState["d"] == null)
            {
                return 0;
            }
            return int.Parse(this.ViewState["d"].ToString());
        }
        set
        {
            this.ViewState["d"] = value;
        }
    }

    protected void Page_PreLoad(object sender, EventArgs e)
    {
        this.CreateDynamicControls();
    }

    protected void addControl_Click(object sender, EventArgs e)
    {
        this.NumberOfControls = this.NumberOfControls + 1;
        this.myPanel.Controls.Add(this.CreateTextbox(this.NumberOfControls));
    }

    private void CreateDynamicControls()
    {
        for (int i = 0; i < this.NumberOfControls; i++)
        {
            var t = this.CreateTextbox(i + 1);
            t.TextChanged += (x, y) => this.lblMessage.Text += "<br/>" + (x as TextBox).ID + " " + (x as TextBox).Text;

            this.myPanel.Controls.Add(t);
        }
    }

    private TextBox CreateTextbox(int index)
    {
        var t = new TextBox { ID = "myTextbox" + index.ToString(), Text = "de" };

        return t;
    }
}

ASPX

    <asp:Panel runat="server" ID="myPanel">
    </asp:Panel>
    <asp:Button Text="Add Control" runat="server" ID="addControl" OnClick="addControl_Click" />
    <asp:Label ID="lblMessage" runat="server" />

Output

enter image description here

Community
  • 1
  • 1
Jupaol
  • 21,107
  • 8
  • 68
  • 100
1

You first code block where you are setting the active View is based on an ItemCommand event, so I'm assuming this fires during a PostBack?

Your code which adds the additional views within Page_Load is only running if not a post back. Try removing the conditional if(!Page.IsPostBack) statement. You need to add dynamic controls on every page lifecycle.

KP.
  • 13,218
  • 3
  • 40
  • 60