ASP.NET Modifying Control Tree Dynamically

I am trying to drop and add controls dynamically to my control tree. For example:

Under a specific condition, I am calling:

    private void resetPanel()
    {
        Panel.Controls.Clear();
        Panel.Controls.Add(Image);
        Panel.Controls.Add(HiddenField);
    }

My main objective is how do I get the added controls to persist across postbacks?

When I call another similar function using textboxes and titles, it persists perfectly. However, with the image it loses its URL and properties.

I understand that for dynamic controls to persist, you must add it on the Init, and you must be responsible for the control tree thus needing to add the dynamic control to the tree on every postback.

So why does it work for textboxes and labels persisting across post backs but you cannot do the control add for images and hiddenfields?

Thanks,
Brian

–Update and Solution–

I have found a mistake in my code, and the HiddenField values do persist across post backs. The solution I have opted for is to use the ViewState to save the values, then restore my dynamic controls on each post back.

–Edit–

Thank you for the replies, and since there may be a better solution to my problem, here is some code that will hopefully show how I am calling the method and why I would need to.

    public void resetTitlePanel()
    {
        // Restylize the panel to initial state
        TitlePanel.Controls.Clear();
        TitlePanel.BorderColor = System.Drawing.Color.Maroon;
        TitlePanel.BorderStyle = BorderStyle.Dashed;
        TitlePanel.Enabled = true;

        // Set the new control properties to initial state
        Label TitleLabel = new Label();
        TitleLabel.ID = "TitleLabel";

        TextBox TitleTxtBox = new TextBox();
        TitleTxtBox.ID = "TitleTxtBox";

        // Add the new controls to the container
        TitlePanel.Controls.Add(TitleLabel);
        TitlePanel.Controls.Add(TitleTxtBox);

        // Set the reference of this to the new dynamic control
        this.TitleLabel = TitleLabel;
        this.TitleTxtBox = TitleTxtBox;
    }

    public void resetImagePanel()
    {
        // Restylize the panel to initial state
        ImagePanel.Controls.Clear();
        ImagePanel.BorderColor = System.Drawing.Color.Blue;
        ImagePanel.BorderStyle = BorderStyle.Dashed;
        ImagePanel.HorizontalAlign = HorizontalAlign.NotSet;

        // Set the new control properties to initial state
        Image AddImage = new Image();
        AddImage.ImageUrl = "~/Resources/Icons/picture_add.png";
        AddImage.ID = "AddImage";

        HiddenField HiddenImage = new HiddenField();
        HiddenImage.ID = "HiddenImage";

        // Add the new controls to the container
        ImagePanel.Controls.Add(AddImage);
        ImagePanel.Controls.Add(HiddenImage);

        // Set the reference of this to the new dynamic control
        this.AddImage = AddImage;
        this.HiddenImage = HiddenImage;
    }

The Calling Method:

private void copyFromSlide(TemplateControl destination, Template source)
    {
        // Reset the template
        destination.resetTitlePanel();
        destination.resetImagePanel();

        destination.Title = source.Title;
        // Find the path from the database and assign it to the control
        destination.ImagePath = modData.getImagePath((int)source.ImageID);
    }

So… I understand that the code is complex, perhaps more than it should be. Further, I am just a beginner so it may be of worse quality, and I apologize for that.

Key notes are:

  • There are 2 user controls that are interacting with each other.
  • This works completely fine on !IsPostback.
  • The ViewStateEnable is true on default, even if I assign it true explicitly, I get the same results.
  • This works completely for the title panel which consists of a label and textbox, both of which retains its value.
  • I know I am mixing static and dynamic controls together. I am used to C, so I am unsure if I could just move the object pointer to the new dynamic object.

The problem is, when assigning the image path, the value does not retain on postback.

I need to drop and re-add controls because under specific conditions I will drop the controls and add labels, which as noted, have no problem. The reason why I believe that I do not need to initialize the controls over again is because I am adding to a rooted panel as demonstrated by:

http://weblogs.asp.net/infinitiesloop/archive/2006/08/30/TRULY-Understanding-Dynamic-Controls-_2800_Part-3_2900_.aspx

I hope this adds some clarity.

Thanks once again,

-Brian

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

ViewState does not track changes until the InitComplete event fires. If you make changes and store them in ViewState before then (for example in Init) these changes will not generate a new viewstate key. Init should be used to reconstruct your control from viewstate. Events after the Init event is where you should set new values for these controls in view state so that they will be persisted back.

In response to your second question: The Image and HiddenField controls do not respond to any events (e.g. click event) and therefore do not need to be reconstructed. This is why you are seeing the different behavoir between the TextBox and Label controls vs the Image and HiddenField controls.

It may be easier to store the data that determines when to add and remove those controls in the page view state and just recreate the controls on every page load.

Method 2

Have you enabled ViewState on these controls?

There are some things in the Remarks section of this document you may want to check out here

Method 3

What you need to do is to always have all your controls added to the page (or user control) before OnLoad() happens (typically on OnInit()).

This is because ASP.NET loads control values from ViewState or Request.Form on OnLoad().

In fact between postbacks none of the “control”s are persisted, it’s only control values which are preserved between postbacks either in ViewState or Request.Form. (No matter if they are added in Markup or Dynamically) as I said above, the only thing that is important is that the control is added to the page before OnLoad().

I should add even if you add your element after OnLoad you still can read control’s value (in postback) like this:

Request.Form[txtName.UniqueID]

for more information about controls life cycle in ASP.NET see here;

http://msdn.microsoft.com/en-us/library/ms178472.aspx


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x