I have a tricky dynamic/programmatic creation issue which is I think different from any of the other ones I've been reading about here, i.e. "how do I programmatically create a column?", "how do I programmatically create a grid?" etc. I'm familiar with all the online references regarding those and have no problems there. My scenario:
- I have a RadGrid that is declared statically in the ASPX page.
- This RadGrid contains all GridBoundColumns, except for one GridTemplateColumn.
- In this GridTemplateColumn, I have only an empty <ItemTemplate></ItemTemplate> declared. (I also tried declaring an empty <EditItemTemplate></EditItemTemplate>, makes no difference.)
- Based on a condition that is only available after the RadGrid is databound (i.e. I perform a check on the contents of a column, similar to "((TextBox)gridItem["RenderHint"].Controls).Text")...
- ...I then dynamically create a control and add it to the GridTemplateColumn (e.g. create a TextBox tb, then do something like "gridItem["Value"].Controls.Add(tb);"). I've found that since the condition is based on the data in the item, I need to do this step in ItemDataBound.
Everything I've described so far works perfectly. So here's where the trouble begins.
When it comes time to persist data back to the DB, in my ItemCommand for the RadGrid which receives the "Save" (from e.CommandName), I have a call to GridEditableItem.ExtractValues. This call to ExtractValues finds and pulls data for every other column (which is in edit mode at any rate), except for my GridTemplateColumn! As described above, this is the column where I am dynamically instantiating and adding a control.
If I perform the instantiation and addition earlier as a test (e.g. Page_Init), then of course the control is found - but my condition which is based on data is not yet available. In other words, even though I would love to build the grid programmatically in Page_Init, I can't do so because I don't know what kind of control I need to instantiate that early!
Ideas please? Regards,
8 Answers, 1 is accepted
GridEditableItem.ExtractValues() can be used only for databound fields, meaning that you cannot use it for GridTemplateColumn unless you have declared a control inside that uses two-way binding with Bind() expression.
You will need to find the control you have created inside your template field and extract its value manually.
the Telerik team
Ok, I see! Thanks much for the reply.
However, in following your suggestion, I find that I'm wrestling now with a deeper issue (which may have been the original issue), which is: when I query the GridTemplateColumns controls collection, I am finding that the count of controls is zero. For example, something like this...
...throws an exception because it finds 0 controls inside that column.
During the static declaration part of the GridTemplateColumn, should I be specifying just <ItemTemplate></ItemTemplate> or also <EditItemTemplate></EditItemTemplate>? I assume that after I make a pass through the RadGrid's items in order to turn them all into Edit mode, the EditItemTemplate becomes available, and that's where I end up depositing my dynamically created controls?
When the grid is in editmode the control is added to EditItemTemplate of the TemplateColumn. You can use the following code to add the control into the EditItemTemplate:
And to retrieve the value, you can try out teh following code:
Thanks for the input. I believe I've already tried that - the only difference being not using the FindControl() method, but instead trying to reference the control directly, such as ((TextBox)gridItem["MyGridTemplateColumnUniqueName"].Controls).Text. Will controls added in the way you describe (in the ItemDataBound event) exist automatically after a post-back? My understanding was that they didn't... Still, I'll give it a shot.
BTW I'm trying to retrieve values for saving in the RadGrid's OnItemCommand event (e.g. checking for e.CommandName = "Save"). Is there a better event I should use, for example which might avoid losing controls that were added programmatically?
Since thinking more about this, I realize that I can have the entire set of data to be rendered already available right in the Page_Init event, but then it's difficult for me to conceive how to build the entire RadGrid in Page_Init because: without access to the natural row-by-row ItemCreated/ItemDataBound event, how do I specify which row should get which dynamic control? For example: let's say the data I get back indicates the following:
- Row 1: based on data, dynamically created control should be a TextBox
- Row 2: based on data, dynamically created control should be TextBox
- Row 3: based on data, dynamically created control should be Drop-Down
- Row 4: based on data, dynamically created control should be a CheckBox
- Row 5: based on data, dynamically created control should be TextBox
Now, of course this exact thing is possible to do in the ItemDataBound event... but this leads me to why I posted in the first place, because it seems when I add controls in that event, they are either inaccessible or disappear when it comes time to try to save!
Is what I'm trying possible using the RadGrid? Regards,
Just replying to my own thread in case anybody travels down this path in the future. Basically, to answer my own question: it is indeed not possible to do what I was attempting - at least probably not without some insane custom programming.
However, I have indeed managed to implement a workaround that gets me fully to what I wanted to accomplish; after I have completed the work (in crunch time now), I'll post it here in the hopes that it may benefit someone.
Thanks again to all who chimed in.
If you have been successful in accessing the controls created in ItemDataBound in ItemCommand event, it will be helpful if you can share it.
I believe the help document link below will help clarify your concerns regarding dynamically created controls in ItemCreated and ItemDataBound event.
Distinguishing the major differences between ItemCreated and ItemDataBound events
Another suggestion would be to add the controls in the design and hide or show them conditionally in the ItemDataBound event.