I have a requirement which adds html/aspx components from code behind. The components can be either Check box or Radio button and options for them comes from the Database.
So what is the best approach to do this. Is user control helps here?
You should generally determine and add such controls via the page OnInit overload or Page_Init event, and be sure you do it on all requests, including postbacks.
Define local variables to hold the objects you may create (it could be a List<> if you don't know how many will exist ahead of time), and instantiate them as any other object, set their properties, and then add them to the Controls collection of the container item they should be in; By default, they will be added to the end of the container, but you can Insert them instead of Add if you like.
Assuming you re-create them like this every time, and do it during Init, you can then access them - including viewstate, if applicable - from the Load event/overload.
Related
I am creating a server control (inheriting from CompositeControl).
The control comprises of several data bound drop down lists (and some textboxes etc).
The drop down lists form a hierarchy, so are dependent on each other... eg
ddlCountry
-ddlCounty
--ddlCity
When ddlCountry is selected, this should refresh the list of ddlCounty... and so on with the ddlCity etc.
I would like to access the value of the ddlCountry within the control, so I can set the data source for second ddl (ddlCounty) accordingly,
but in CreateChildControls() the viewstate does not seem to have loaded the ddlCountry user selection yet into the control, so I get an empty string.
I also need to provide these ddl values as a public property.
This is getting quite messy, with the use of ReCreateChildControls() etc... which I'm sure is wrong.
My Question:
Can anyone suggest the correct pattern / set of rules to abide by to create this server control
eg
initialise controls OnInit
DataBind on OnLoad
Put EnsureChildControls() at beginning of any property: get or set
I assume there must be a correct way of implementing this, but cannot find any documentation or example to get this working as you would expect of a standard control.
Thanks
EDIT: I needed to skip control creation during post back -- see my answer below.
I'm working on a very basic front end to a simple tool and I wanted to present some data in a much more sorted and useful way, instead of making one huge wall of text. I found this tutorial on building a simple tabbed interface using MultiView, but have run into a bizarre problem. I can't use Ajax tabs because of legal hissy fits over 3rd party software.
My webpage is a basic ASP.NET page with a user control plopped in the middle of it. In this control's ascx file, I defined the Menu (empty) and the MultiView (also empty) so that I can dynamically populate the tabs with content driven from an external file.
When the default page's OnInitComplete function is called, I call through to the user control to load the data file, then build out the tabs and the view content based on the loaded data. I tried doing this from PageLoad, PreInit, and CreateChildControls, but I kept getting an errors saying that I was setting the the MultiView's active view index at an invalid time (and also that there were 0 views despite the fact I just added a bunch of them):
ActiveViewIndex is being set to '0'. It must be smaller than the
current number of View controls '0'. For dynamically added views, make
sure they are added before or in Page_PreInit event.
But OnInitComplete appears to work just fine, so I went with that.
I iterate over the loaded data (multiple lists of strings), and for each list, I add a MenuItem with the list's title to the Menu and a View to the MultiView. The View is populated with a table->row->cell as in the above tutorial. In the cell, I add the list title and a CheckBoxList data bound to the list of strings.
So far so good, but when I click on a tab (or one of the checkboxes, etc) and there is a postback or something like that (the screen flashes as the site redraws itself), there is now a duplicate set of MenuItems immediately after the original. Each time I click on a tab or checkbox, another set of menu items are added.
I clear the MenuItem's Items list prior to building the controls and I verify that the controls hierarchy is structurally as expected after the control construction. Yet when one of my callbacks is called, my MenuItem list magically has some items added to it. None of my other controls appear affected at all. As a hack, I can remove the duplicates manually in my menu's OnMenuItemClick event, but I'd have to do the same in any of the callbacks I receive. Obviously I'd rather prevent this from happening. This has me stumped and I haven't been able to find anything online about it. Why would one set of controls have some content duplicated, yet every other control maintain its state correctly? My code is really simple so there isn't a way to add additional menu items without also adding the views. Anyway, there are a correct number of items prior to clicking on the tab/checkbox, an additional set immediately following in the callback.
This is my first time using ASP.NET, so I'm learning as I go. :) Thanks!
My problem was that I was not testing for postback before creating the controls. The code below is working for me.
In my user control's code behind:
protected void OnInitComplete( EventArgs e )
{
if( !Page.IsPostBack )
{
CreateMyControls();
}
}
I have a user control that contains only a text box and on another form I add this user control dynamically, a user can add the user control many times. I use a session variable to recreate the user control (maybe this approach doesn't sound cool). After recreating the control the value of the textbox disappears, obviously. Is there any solution to maintain the state of the user control on postback?
If you add dynamic controls back to the control during the correct Page Life Cycle event(PreInit) they will maintain their state through the IPostBackDataHandler interface.
PreInit - Create or re-create dynamic controls.
I've had the same problem in the past.
What I did was give the dynamically-added control an ID, and made sure it retained that ID also on postback (in my case, I kept all the information in the session, and re-created the controls).
Once the postbacked control has the same ID as as before, Microsoft did magic and refilled the controls with the pre-postback values.
Use the object cache. Add the usercontrol into the cache and retrieve it when you need it.
You can see a nice example of how this works at: ASP.net-Tutorials Cache and Object Cache.
I am also learning asp.net now and found that quite a nice explanation. I also used the Microsoft Library
Every server control that inherits the IPostBackDataHandler interface has a LoadPostData method that processes the postback data. When control is implemented by a class (page, form, placeholders, controls etc), that class calls the LoadPostData method and passes the posted data and key to maintain control states.
All you need to do is to re-instantiate / reinitialize dynamic controls before or within page load event each and every time during postback and add this control to page / forms / placeholders. Then the posted data will automatically be assigned to the control by calling LoadPostData method by the parent control.
Check this article to learn how to write code for dynamic control -
How to maintain dynamic control events, data during postback in asp.net
I have an existing ASP.NET 3.5 application with a webform containing a FormView control used to perform CRUD operations on a domain object. A new requirement adds some dynamic content to the domain object that needs to be reflected in the FormView. This means that I need to generate those controls on-the-fly based on the bound object.
I am using an ObjectDataSource for the FormView that returns the domain object for binding. The domain object will now have a property that returns a collection of Section objects with each Section containing a list of Questions. In the middle of my form, I need to display each section with the list of questions and a textbox that allows the user to input the answer.
I am able to generate the UI a number of different ways but I have yet to find a way that includes data for the dynamic fields when the page is posted back. Because I won't know the 'schema' until the FormView is data-bound, I'm wondering if I'm too late in the pipeline for postback data to be handled properly.
What is the best way for me to generate these fields so the data is posted back correctly?
UPDATE
I'm still looking for the best way to accomplish this task but I've found a solution that at least works. In short, I am creating the dynamic content in the FormView's DataBound event handler because this is the first place in the pipeline that I can always get references to the FormView's controls. Then I follow Muhammed's suggestion and pull the values right out of the Request.Form collection and put them into the EventArgs objects in the FormView's ItemInserting and ItemUpdating handlers.
This isn't so straight forward as each control has to have a unique ID that I can then use to locate the value - which isn't so bad. However, I had to implement custom logic in the data source to then map these values into the data-bound object.
All-in-all, not too bad but certainly not something I'd want to duplicate in other solutions so I'm hoping there's still a better way.
When you want to get the value from the dynamic generated field, you should get it from the Request.Form collection and pass it into the ItemInserting event of FormView. e.g.
protected void frmAsset_ItemInserting(object sender, FormViewInsertEventArgs e)
{
e.Values["FieldName"] = Request.Form[ControlClientID];
}
Please note, your controls should be recreated on postback to get the value.
I've got an asp.net page that has c# code-behind that does some stuff in the Page_Load() method (like query a database and make a few other calls to populate objects with data). I then display this data on the page. This all works fine. I set up a couple of postbacks so that when a value in a listbox is clicked, a panel control is filled with the rest of the corresponding object's data. I thought postbacks were the right way to do this, but this causes the (entire class?) to be re-called, which re-initializes my objects and destroys the data I want to keep.
Will some form of partial-postback solve this problem, or is there a better way to implement what I'm trying to do?
I don't want to re-populate the objects every time a postback is called, as that takes a database query, and I want to avoid re-querying every time something is clicked...
I've found many questions regarding persisting Javascript objects, but nothing that really seems to address this. I'm using .Net 4.0
Put the objects into the Session for the current user.
Put all your initialization stuff in an (!IsPostback) { } and use partial postbacks. That way the initialization code doesn't get called again during the postbacks.
Why don't you cache the object?
Caching API, Using the Cache Object:
http://msdn.microsoft.com/en-us/library/aa478965.aspx#aspnet-cachingtechniquesbestpract_topic4