[英] dynamically added user control saving values after postback

Here's my issue. I have a usercontrol that I want to allow users to add as many instances of as necessary using a button click (each time a button is clicked, I want to add another instance of my user control to a Panel). It works fine the first time, but each additional post back removes all of the added controls. I have no problem keeping track of the number of user controls a user has added but how do I ensure they stay in the same state they were before the postback? I've read some posts about people using SaveViewState and LoadViewState but I haven't been able to find any examples.


My biggest issue is ensuring that all of the text boxes and dropdownlists from each user control stays populated with the same text/selected value/data after each post back


Thanks in advance, Ben


7 个解决方案



Since you're programmatically adding controls to your page, you'll need to recreate them on EACH postback.


Also, it's necessary that you recreate programmatically added controls on PreInit or Init event of the page. This is for proper viewstate restoring event management.


If you don't do this, control will be gone on postback and they won't handle any event.



Although is recommended to add dynamically controls on PreInit or Init it's true (as Dustin Hodges says) that it may work if you add them on page_load. I'd say you should avoid it unless you have no other option.

雖然建議在PreInit或Init上添加動態控件,但是如果你在page_load上添加它可能會有效(如Dustin Hodges所說)。除非你別無選擇,否則你應該避免它。

You may be able to get away with loading your controls in the Page_Load event handler and maintaining the view state properly.
It all depends on whether or not you are setting any properties of the dynamically loaded controls programmatically and, if so, when you're doing it relative to the Controls.Add(dynamicControl) line.
A thorough discussion of this is a bit beyond the scope of this article, but the reason it may work is because the Controls property's Add() method recursively loads the parent's view state into its children, even though the load view state stage has passed.


Source MSDN



If you are keeping track of the number of controls the user has added you need to recreate the controls the user added previously, preferably in Page_Init or Page_Load. Add something like this to that handler:


for(int i=0; i<NumberOfControlsUserHasAdded; i++)
    //todo:  change this to the appropriate user control
    TextBox tb = new TextBox();
    tb.ID = "tb" + i.ToString();
    //todo:  add to appropriate control collection

If you do it this way, the state of the controls should be maintained because when you add the tb control to a controls collection it plays catch up with events and should automagically restore its viewstate.


You shouldn't have to keep track of their state in session as in most cases it will be stored in the viewstate for you




I had a nightmare of a time trying to pull this off on an old project. In the intermediate time, I've discovered that I know a lot less about web development than I thought (reading this website is a great way to humble yourself on a daily -- if not hourly -- basis). In that project, Page.IsPostBack was totally useless to me because I had dynamically instantiated the controls.

我有一個噩夢,試圖在一個舊項目上解決這個問題。在中間階段,我發現我對網絡開發的了解遠遠少於我的想法(閱讀這個網站是一個很好的方式來謙卑自己每天 - 如果不是每小時 - 基礎上)。在那個項目中,Page.IsPostBack對我來說完全沒用,因為我已經動態地實例化了控件。

That being said, the best thing I can suggest is to consider using the Session variable. If you have a class (or a collection of a class) that represents the data you capture from the page, then perhaps it'd be easiest to store values in that class/collection to improve code readability, and then write it out to the Session.




Look at your PageLoad and add if(!this.IsPostBack) before the line where you clear the panel.


this is of course just a guess, but I have seen many questions where the problem was related to this.




I think what may be happening is when you click the button to add, Page_Load fires which creates you a brand new page. Then, the button click method adds the control and the page finishes rendering. When you click it the second time, Page_Load creates your page and the button click method again creates a control and adds it to the page. Unfortunately, the one you added previously is no longer there.

我認為可能發生的事情是當你點擊按鈕添加,Page_Load fires會為你創建一個全新的頁面。然后,按鈕單擊方法添加控件,頁面完成渲染。當您第二次單擊它時,Page_Load會創建您的頁面,再次按鈕單擊方法會創建一個控件並將其添加到頁面中。不幸的是,你之前添加的那個不再存在。

What if you added the controls to a Repeater? The Repeater's view state may keep track of each control you add so that on post-back, it's not blown away.

如果您將控件添加到Repeater會怎樣? Repeater的視圖狀態可以跟蹤您添加的每個控件,以便在回發后,它不會被吹走。



It's an ugly solution if you have a ton of users, but you could stick the usercontrols themselves into the session. I do this with my footer control because I don't want to hit the db every time the page changes to recreate the footer.


This solutions can get really tasking on the server if you have a lot of users and they use this feature a lot. At least I think it will...


But you can just repopulate your placeholder that has the usercontrols in it on page_load. I can put up an example shortly.


Example of what I do:


if (Session["footer"] == null)
 Session["footer"] = new Footer(LinksRules.BuildFooterLinks((int)WebSiteSections.Main));// where Footer is my control

Like a singleton pattern sort of...


So as I see it you could do this on anything that will cause a postback


Session["DynamicControls"] = PlaceHolder.Controls;

Session [“DynamicControls”] = PlaceHolder.Controls;

and in the page-Load method you could:


foreach(var control in (List<Controls>)Session["DynamicControls"])

and if the session object is null just add a single one like they've never been there..


I believe this will hang on to the data inside the controls like you want.




  © 2014-2022 联系我们: