2

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

2
  • Are you saying that you are ALSO adding dynamic textboxes and labels as well as dynamic images and hiddenfields? Are you saying that your adding dynamic textboxes and labels and they persist, whereas the images and hidden fields do not? Commented Jul 21, 2011 at 17:23
  • Hi Gangelo, that is what I am saying more-or-less. The textboxes and labels are added in a function apart from the images and hiddenfields though. Commented Jul 21, 2011 at 19:49

3 Answers 3

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.

Sign up to request clarification or add additional context in comments.

4 Comments

Hi Charles, Thanks for the reply. I have been looking further into this. I did not know of any events label controls would respond to. Furthermore, even if I use a static control, when I alter the image URL, it is not sticking after post back. Albeit, I am changing the imageURL before the preRender but after the Load, from another User Control's Page Load. Haha, perhaps the complexity is preventing it from functioning as expected. Thanks. -Brian
I updated my answer. you may have better luck just creating the tree every time from the data that determines what should be in the tree. You can store that data in the page viewstate instead.
Hi Charles, I completely agree with your answer. Thanks for taking the time to answer my question.
Hi Charles, Just to let you know I tried your answer, and it works perfectly! Thanks again!
1

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

6 Comments

Hi Gangelo, I have enabled the ViewState on these controls, but the imageURL still does not perist. Thanks.
The view state for these controls are enabled by default.
@Brian - when you view the rendered page source, are you sure that the control is actually being rendered? Are you saying you see the Image on !Page.IsPostBack and the Image is STILL rendered on Page.IsPostBack BUT the ImageUrl property gets wiped out?
@Charles - he could be disabling it by chance.
@gangelo - I agree, its just useful information that goes along with your answer.
|
0

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

5 Comments

Hi Valipour, Thanks for the reply. Would this be true for properties such as Image.imageURL? Thanks.
Why do you need ImageUrl to be loaded from Request? ImageUrl is not part of form, so it's always initializes, isn't it?
Hi Valipour, you are correct. The ImageUrl is not part of the form. The control I am having problems with is a dynamically loaded image not persisting across postbacks. Since you were saying how an element's value persists across postback not the control itself, even after the onload. I was wondering how I can access the image's url value. Otherwise, on postback the image breaks.
The whole point I'm mentioning in my answer is that: you need to dynamically add your image in "OnInit". ImageUrl is not read from form, so you must be assigning it, but OnInit() always happens (before anything else) so your image will have ImageUrl after that. It will help a lot if you show us when u are calling that function.
Hi Valipour, Thanks. I have added code to show you the calling function. I thank you for your help!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.