Proper use of asp.net webforms lifecycle - c#

This is really a more general question, but the only way I can think to ask it is with a specific example.
We currently have a webpart with an SPGridView. As it is now, the GV and all bound fields are created in CreateChildControls, the data is retrieved and bound in OnPreRender. The columns are static so this works fine.
CreateChildControls{
// create and configure the gridview
// create all bound fields and add them to the gridview
// add the gridview to the page
}
OnPreRender{
// get the data and bind it to the gridview
}
Now we need to change the columns to be dependent on the selection made by the user from a dropdown list. Within CreateChildControls we cannot get the value from the dropdown control so we can't conditionally add bound fields. My question is, what is the best practice here? We could create all possible bound fields in CreateChildControls and then only add the appropriate fields to the GV in OnPreRender. We could just move the creation of all of the bound fields entirely into OnPreRender. And there are really many other options.
CreateChildControls{
// create and configure the gridview
// create ALL bound fields here?
// add the gridview to the page
}
OnPreRender{
// or maybe create only the applicable bound fields here?
// add the appropriate fields to the gridview
// get the data and bind it to the gridview
}
And in a more general sense, what really constitutes "creating" a control (the purpose of CreateChildControls)? The question really extends to any control which could have dynamic content. Where is the appropriate place to add entries into your dropdown list, etc. There are many ways that work, but which is "right"? Is adding the selections into your dropdown part of "creating" the control? Is it dependent on whether or not the selections are dynamic?

BoundField is not a control and the Columns collection in gridview is state managed so you can safely add the columns in the PreRender event before you databind the control.

Related

How to set up page loading in ASP.Net for dynamic gridviews?

Here is how my code is set up.
The webpage itself works like this:
You have a drop down that allows you to select between different values. Lets call it dropdown A. Depending on the value selected, a gridview gets generated.
How generation works:
When a item in the dropdown A gets selected, inside the selectedIndexChanged is a method call to a function that creates a DataTable. That datatable gets binded to the gridview inside selectIndexChanged.
When it gets bounded, onRowBoundEvent gets called, and this is where I add all the necessary controls with unique IDs.
There is a button called saved that looks at the data in gridview, and saves it.
Problem: When I press save, there are no controls in the gridview for me to find.
I can use findControl since I know all the ids, but how do I make the controls stick around?
If I bind it in the page_load, how do I know what gridview to generate since if I select a value from dropdown A, page_load still fires before I can get a selection value from dropdown A, so I can't make a simple conditional statement based on the dropdown value.
I can't show any code, sorry. But this is more of a conceptual question I have.
I was able to figure this out on my own.
PrePage_Load during the project lifecycle has access to controls. Dropdown A in my example can be accessed in PrePage_Load, allowing me to get the necessary values and set them before Page_Load starts.
For controls in the gridview, I made it so the gridview does not automatically load from viewstate, and I rebuilt the gridview myself during page_load.

Correct Pattern for creating Server Controls?

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

What is the best way to persist the usercontrol values without having to postback or to write server-side code?

Scenario: I am having a user control which has two drop down lists. The values of the second drop down is fetched and populated depending on the selection made in the first. So, the first drop down makes a postback and pulls the data for the second. The second dropdown, therefore, does not need any postbacks on any selection changes.
This user control is being used on a page in a gridview, and therefore it repeats several times depending on the number of records in the grid.
Problem: When I make a selection in any of the dropdowns, my previous selections in all the user control dropdowns are lost and reset to the first item in the dropdown list.
Solution that works for me: I am able to fix this behavior by setting the selections made in viewstate on SelectedIndexChanged event for the respective DropDownList. But I want to avoid the postback being made by the second dropdown as it does not do anything related to UI (changing or pulling additional data to update on screen) and from the user perspective, its a waste of time and thus irritating.
I have also tried using javascript to write the values I want to persist into hidden fields, but the hidden field values are empty when the page is refreshed.
So, What is the best way to persist the dropdown values without having to postback or to write server-side code?
Thanks in advance.
#Aniruddha , I guess you are filling the first dropdown at the page load of UserControl so write that code in !IsPostBack constraint, i.e.
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack){
// Write your existing drop down bind or other code here.
}
}
Aniruddha you are probably binding you grid in the Page_Load and so in this case bind the grid under constraint of !IsPostBack as above
Hope this will help you !!

Binding multiple data types to a single column in Gridview

Can anyone tell me if what is detailed in this example is possible with GridView using TemplateColumns. http://www.codeproject.com/KB/webforms/CustomDataGridColumn.aspx
I need to dynamically generate a GridView that may need not have one datatype in a column. Say Column 1 could have Checkbox or TextBox control (based on a logic, of course)
I tried implementing ITemplate and adding custom controls in InstantiateIn(), but as far as I understand - the binding here on on a per column level and not on per Item level.
How can I acheive this?
Thanks in advance. I can stub out the code I have if the question needs more clarification.
Yes, Telerik's RadGrid supports this.
The same code will work with only minor changes. For example, ListItemType becomes GridItemType. DataGridItem becomes GridDataItem, etc. Also, the way Telerik creates the controls means some of the indices need to change. For example, their ItemDataBound event has this code:
string dataType = e.Item.Cells[0].Text;
but with a Telerik RadGrid, that needs to be:
string dataType = e.Item.Cells[2].Text;
Other than those kinds of minor changes, it all works with RadGrid.
Note: When I see code samples from Telerik, they generally go a different route. The way I've seen them provide custom content for a cell is to put your customization logic in the ItemCreated event. That will be called for each row. So you can have the column's template contain all the possible controls and then in ItemCreating event, modify the instance of that template by setting the correct control to Visible based on your logic (this is the approach used in the article you linked to). Or you could create only a single specific control in that event for the correct type of control. Here is the documentation for the ItemCreated event and also a code sample from Telerik that modifies a LinkButton for each row but the same approach can be used.

Generate data-bound FormView fields on-the-fly

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.

Categories

Resources