I created a CustomDataBoundControl. I implemented CreateChildControls(), but I am not actively doing anything to support viewstate and thus, I loose the data after a postback. I was looking in to this article: http://msdn.microsoft.com/en-us/library/aa479016.aspx
My problem is that the way the sample works with ViewState is using a Pair object, which holds key-value pairs and recreates a known data type in the collection of itemsIStateManager` implementation.
My control is more generic. I do not know the type of the objects coming in to the datasource property and I create the child controls via reflection in to the datasource objects. I create a Table control and fill it with TableRow controls, which I fill with TableCell controls.
I can't seem to bridge this gap between Dino`s example and my real-world implementation.
When it comes to data source controls, you don't use ViewState to retain the data. As long as your building a control tree, the .NET framework will reload the viewstate of the controls in the control state. You just need to store the viewstate for the core properties of the control, plus the number of items rendered. This way, you can rerender the same control tree.
create the control tree on init to maintain the ViewState, you need not populate the data in your controls but just create the controls. As per the page flow ViewState is enabled for the controls which are created in OnInit. Hope this helps.
Related
After wasting hours for trying to solve dynamic user control's ViewState being lost I decided to disable ViewState for good.
The question is what should I do now? How should I keep my dynamic control's state so that they don't get lost after postbacks. I am thinking about using Session instead but that means I have to generate unique keys for each page/tab opened by the user so that values are not overwritten (right?). What is the best way of doing it?
For ensuring view-state of dynamic user controls, you need to ensure that
Dynamic controls are created in every post-back scenario
They are created as early as possible in page life cycle - init and load state are best bets (loading them in control events is unlikely to work)
The dynamic control hierarchy should be exactly the same and all controls in hierarchy should have ids same as in previous request
Always assign ids (otherwise they may get auto-generated and can have different values) and assignment should happen before adding the control in control tree.
Changing the view-state store to say session instead of hidden field will not solve the problems where ASP.NET run-time has already loaded the view-state or is unable to associate control with its view-state data (inferred from id and hierarchy)
I am creating a custom control extending WebControl. This web control allows the consumer to define a collection of columns in markup, something like this:
<Custom:CustomGrid>
<Columns>
<Custom:DataColumn HeaderText="FirstName" />
<Custom:DataColumn HeaderText="LastName" />
</Columns>
and put an IEnumerable in a DataSource property and this is rendered out to a table.
This control also allows paging. The IEnumerable in DataSource is the full list, and I display a page of the list at a time. I am already saving the current page, number of rows per page, etc. to viewstate. Should I also put the full list in viewstate? Maybe session?
This list can become a bit hefty. Maybe save in session with a random key, which is saved in viewstate?
What is the best practice here?
Edit: I don't think it's right to impose that all types in the IEnumerable be serializable. Is that fair? So do I need to copy the data source to some other data structure for serialization?
Edit 2: Even if I do use a base control instead of implementing RenderChildControls I will need to implement CreateChildControls, but I will still need to persist the data somewhere, or did I miss the point of the base class?
Indeed, not all IEnumerable instances will be serializable.
If the query is cheap to run I wouldn't persist the whole data set but just run the query again for a different page or a change in the sort order.
If you put the data in viewstate you'll end up with huge pages. Session state might be acceptable if you don't have many users, but large data sets with lots of users won't scale well. What if I bind a million rows to your control? Or what if your control was used in a repeater and shown 100 times on a page?
Are you sure you need to persist the data? This isn't premature optimisation is it?
Remember that your control is a UI component. The viewstate should hold enough information to maintain the UI state as it is. A change in state (e.g.: switching to a different page of results) is something for which your control should pass responsibility to the data source.
Take a look at good old GridView. It displays what you give it and remembers that. If you're using paging then it raises an event to say "the user has changed page; give me page x of data". For me, that's the best practice for a UI control.
For implementing databound control it is better to use base class which was designed to perform such task. For example in ASP.NET exist CompositeDataboundControl which can be used as a base class to implement custom data bound controls. I can advice to review the following Dino Esposito article:
http://msdn.microsoft.com/en-us/library/aa479016.aspx.
Basically if you create control like ASP.NET gridview then it is store values in viewstate. To be more clear it is create number of the DataRow controls which saved assigned values in viewstate. During postback it recreates the same number of rows and values are restored from viewstate. If you will save only datasource for example in session without using viewstate then you will need to redatabind data to your grid during every postback. So, if you create Server control similar to gridview then approach described in the Dino Esposito post will be very helpful because it shows how to create control similar to ASP.NET Server GridView control.
In our project we have a form in which we want to persist the state within a repeater (or an alternative like datalist).
This form is about creating an invoice that'll consist out of 'rows', but those shouldn't be stored until it's actually processed completely. Therefore we're storing it in the ViewState.
Now it isn't important at all that the controls inside the repeater actually persist their state, but it is important that we can track any changes made to them before rebuilding the repeater on the server-side.
Is there any way of achieving this?
Extra information:
Controls: RadTextBox, RadNumericTextBox, RadComboBox, RequiredFieldValidator (Rad Controls are from the telerik library)
.Net Framework: 4.0
DataSource type: List<T>
Thanks
I have a silverlight page which has about 5 user controls. Most of the controls are getting the same data from the database which I wanted to save some round trips to DB. I wanted to get the data in the main page and then pass it to the child controls. I tried creating a public property in the controls and setting them from the main page.
What is the best way of doing this?
Thanks.
From your description, it sounds like data binding would be your best approach (MSDN documentation). If you set the main control's DataContext to the object you retrieved from the database, all of the controls in that page will have access to the DataContext as well. This would also allow you to leverage data binding expressions to populate the properties of the UserControls' children.
I am writing a survey generating system in asp.net. i asked an ealier question about the best way to create controls that can be passed about as variables. This was problematic with user controls so i was advised to use custom controls and a quick way to do this was to inherit from the panel control and just add a bunch of standard controls the the controls collection by overriding the CreateChildControls method. This way i could create my "survey" controls,which are basically Questions in the survey. THe question controls are then dynamically added to the page. This all works well but know i have come to the point that i want to try and retrieve the values from these controls and i seem to be lost in a nether world of of viewstates and page lifecycles. I can ensure that the dynamically added text boxes have a known ID, however even if i add the parent control in the page init handler the CreateChildControls method does not run until after until after the viewstate is loaded. I cannot work out how to retreive the values from these text boxes.
You can call the EnsureChildControls method on the init handler of your control to ensure CreateChildControls is called before the ViewState is loaded.
You certainly seem to be doing this the hard way. TextBox values are not saved in the Viewstate, they are posted in the request.
Why aren't you using a UserControl here? So you can "pass" it somewhere? what exactly are you trying to do?