Dynamically added controls in Asp.Net

2020-01-27 19:44发布

I'm trying to wrap my head around asp.net. I have a background as a long time php developer, but I'm now facing the task of learning asp.net and I'm having some trouble with it. It might very well be because I'm trying to force the framework into something it is not intended for - so I'd like to learn how to do it "the right way". :-)

My problem is how to add controls to a page programmatically at runtime. As far as I can figure out you need to create the controls at page_init as they otherwise disappears at the next PostBack. But many times I'm facing the problem that I don't know which controls to add in page_init as it is dependent on values from at previous PostBack.

A simple scenario could be a form with a dropdown control added in the designer. The dropdown is set to AutoPostBack. When the PostBack occur I need to render one or more controls denepending on the selected value from the dropdown control and preferably have those controls act as if they had been added by the design (as in "when posted back, behave "properly").

Am I going down the wrong path here?

9条回答
孤傲高冷的网名
2楼-- · 2020-01-27 19:56

You must add your control inside OnInit event and viewstate will be preserved. Don't use if(ispostback), because controls must be added every time, event in postback!
(De)Serialization of viewstate happens after OnInit and before OnLoad, so your viewstate persistence provider will see dynamically added controls if they are added in OnInit.

But in scenario you're describing, probably multiview or simple hide/show (visible property) will be better solution.
It's because in OnInit event, when you must read dropdown and add new controls, viewstate isn't read (deserialized) yet and you don't know what did user choose! (you can do request.form(), but that feels kinda wrong)

查看更多
孤傲高冷的网名
3楼-- · 2020-01-27 20:00

I ran across this in the book "Pro ASP.NET 3.5 in C# 2008" under the section Dynamic Control Creation:

If you need to re-create a control multiple times, you should perform the control creation in the Page.Load event handler. This has the additional benefit of allowing you to use view state with your dynamic control. Even though view state is normally restored before the Page.Load event, if you create a control in the handler for the Page.Load event, ASP.NET will apply any view state information that it has after the Page.Load event handler ends. This process is automatic.

I have not tested this, but you might look into it.

查看更多
冷血范
4楼-- · 2020-01-27 20:02

Well. If you can get out of creating controls dynamicly, then do so - otherwise, what i whould do is to use Page_Load instead of Page_Init, but instead of placing stuff inside the If Not IsPostBack, then set i just directly in the method.

查看更多
姐就是有狂的资本
5楼-- · 2020-01-27 20:03

Ah, that's the problem with the leaky abstraction of ASP.NET web forms.

Maybe you'll be interested to look at ASP.NET MVC, which was used for the creation of this stackoverflow.com web site? That should be an easier fit for you, coming from a PHP (thus, pedal-to-the-metal when it comes to HTML and Javascript) background.

查看更多
The star\"
6楼-- · 2020-01-27 20:07

After having wrestled with this problem for at while I have come up with these groundrules which seems to work, but YMMV.

  • Use declarative controls whenever possible
  • Use databinding where possible
  • Understand how ViewState works
  • The Visibilty property can go a long way
  • If you must use add controls in an event handler use Aydsman's tip and recreate the controls in an overridden LoadViewState.

TRULY Understanding ViewState is a must-read.

Understanding Dynamic Controls By Example shows some techniques on how to use databinding instead of dynamic controls.

TRULY Understanding Dynamic Controls also clarifies techniques which can be used to avoid dynamic controls.

Hope this helps others with same problems.

查看更多
淡お忘
7楼-- · 2020-01-27 20:13

I agree with the other points made here "If you can get out of creating controls dynamically, then do so..." (by @Jesper Blad Jenson aka) but here is a trick I worked out with dynamically created controls in the past.

The problem becomes chicken and the egg. You need your ViewState to create the control tree and you need your control tree created to get at your ViewState. Well, that's almost correct. There is a way to get at your ViewState values just before the rest of the tree is populated. That is by overriding LoadViewState(...) and SaveViewState(...).

In SaveViewState store the control you wish to create:

protected override object SaveViewState()
{
    object[] myState = new object[2];
    myState[0] = base.SaveViewState();
    myState[1] = controlPickerDropDown.SelectedValue;

    return myState
}

When the framework calls your "LoadViewState" override you'll get back the exact object you returned from "SaveViewState":

protected override void LoadViewState(object savedState) 
{
    object[] myState = (object[])savedState;

    // Here is the trick, use the value you saved here to create your control tree.
    CreateControlBasedOnDropDownValue(myState[1]);

    // Call the base method to ensure everything works correctly.
    base.LoadViewState(myState[0]);
}

I've used this successfully to create ASP.Net pages where a DataSet was serialised to the ViewState to store changes to an entire grid of data allowing the user to make multiple edits with PostBacks and finally commit all their changes in a single "Save" operation.

查看更多
登录 后发表回答