Is there an efficient way to overwrite the HTML output of a header and footer of an ASP.NET GridView control?
I would like to implement a methodology that is similar to the HeaderTemplate tag in an ASP.NET Repeater or does not require to include dynamically building the HTML output in the page code behind. If these two types of options are available with a ASP.NET GridView control.
In a Gridview, you can use the RowCreated event to completely "destroy" and recreate the header and/or footer. During this event, check to see:
if (e.Row.RowType = DataControlRowType.Header)
{
// At this point you have access to e.Row.Cells
// You can now empty the collection and recreate it.
// If you create a singular cell in the collection
// you can then make its ColumnSpan reach across
// the length of the entire table. Then inside this
// cell you can add any set of controls you want.
// I've used this method to combine column headers
// and add specialty controls that simply wouldn't
// working using the HeaderTemplate
}
Since this is done at RowCreated, during RowDataBound you would have access to these controls and can then manipulate them however you like based on data. This is handy for doing complicated calculations in the footer, adjusting images in the header based on sort, etc.
You may want to consider looking into using an ASP.Net Control Adapter. I have used them for very basic things, but just as Scott Guthrie notes:
A control adapter allows you to
plug-into any ASP.NET server control
and override, modify and/or tweak the
rendering output logic of that
control.
The Toolkit also contains several "out of the box" adapters you can draw from for examples, including the GridView. Again, I am not 100% sure you will be able to do exactly what you want, but it is worth checking out for sure. If nothing more than to put another ASP.Net trick under your belt.
You can also inherit the control and override the Render function. I had to do that to fix a shortcoming of the ASP.NET radio button. The basic idea is here, you might be able to modify it for your needs:
http://www.codeproject.com/KB/webforms/How_group_RButtons.aspx
To change cell-by-cell checking on RowCreated is the way to do it e.g. if you wanted to add a drop-down to a column to allow filtering you could do.
if (e.Row.RowType = DataControlRowType.Header)
{
e.Row.Cells[0].Controls.Clear();
var ddlFilter = new DropDownList();
//add options etc
e.Row.Cells[0].Controls.Add(ddlFilter);
}
If you were going to convert to a single cell and add new controls then I would just set ShowHeader=false and put my markup/controls above the gridview
Related
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.
I have an asp.net webforms site with a rather large GridView. The GridView is rendered from a filtered list of data objects.
Some of the data objects have children of the same type.
In my GridView, I'm initially only showing the parent objects. I want to be able to expand the parent to show the child objects, via an Ajax call, and insert the new rows under the parent.
The catch is, they need to follow the same formatting and rendering rules as the parent, and fit in with all the rest of the existing rows. This means that all columns of the new child needs to fit in the columns of the rest of the rendered grid.
I would also like to re-use the existing GridView rendering methods if possible, so I don't have to maintain duplicate code that essentially does the same thing.
I can easily use the DynamicPopulateExtender from the AjaxControlToolkit to call a web service to get the child rows, but that wouldn't easily give me the rendered and formatted HTML that would fit into the already rendered GridView table.
Is there a way to get this to work properly, or is there a different way I should approach this?
Make your Ajax calls and insert the data with jQuery perhaps using a templating engine like jsRender to merge the data. Use the same css classes for the gridview and template to keep the uniform look you want.
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.
My web page will get a set of results from the database and display it to the user. However I am not sure about "number" of results.
Each result will have a panel which contains several controls in itself, an image, several labels, etc.
What is the best way to do this dynamically, eg. create these controls dynamically?
Is it better to use an AJAX control? Should I use Gridview?
Thanks for the help,
Behrouz
You need to give us more details about how each result will look like.
I would being by looking at a repeater control. You don't need to know the number of results that get passed to it. You'll be able to specify a template for how each result will look like and the repeater control will take care of rendering one for each result.
A repeater is probably the better option for that scenario.
Add all the controls you're likely to need and switch them on and off as needed via the item databound event.
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.repeater.itemdatabound.aspx
If the template for each item is the same, use a Repeater. Bind via AJAX if you'd rather bind via web services and save on server-side performance. Then you have to manage everything on the client, which can be tedious, but very performant. Use JQuery to make it easier.
Server-side adding of controls can be a pain, but doable.
HTH.
I'll explain what I'm trying to achieve:
I want to have a situation where I can create as many controls as I want by creating them in a loop in the code behind. I can do this while using PHP, by mixing the PHP code and the HTML code. This allows me to generate actual HTML tags dynamically.
In ASP.NET, I haven't found a way to replicate this functionality.
I've thought about using a loop in the code behind on something like the Init() function to create an array of new() objects, setting their attributes and hoping it is passed into the aspx file, but it didn't work.
How do I do this?
If you want to creat Dynamically ASP.Net Hyperlink control
You can simply do this:
HyperLink hyp = new HyperLink();
hyp.ID = "hypABD";
hyp.NavigateUrl = "";
Page.Controls.Add(hyp);
Well, keep in mind there's a difference between Hyperlinks and LinkButtons in ASP.Net
If you just want Hyperlinks, you can create as many as you want by creating a HyperLink object, creating new objects and then adding them to some control's Controls collection like panel or span or something.
LinkButtons are a little different. You have to use a Repeater control if you want to create a link that posts back to the server. (Well, you don't have to but the alternative is a hack job.)
Hyperlinks can be created by using a Repeater control as well and, if possible is the method I would recommend.
There are lots of ways to do this in asp.net:
If you really wanted to, you could put a loop using <% %> tags directly into the aspx markup, just like with php or classic asp. This is not recommended.
You can put a placeholder or panel control on your form, create as many hyperlink controls or anchor tags as you want in your code behind and add them to the placeholder's controls collection. This is a little better, but still not optimal.
You can put a reasonable number of hyperlink controls on the page, set their visible property to false by default, and "enable" the ones you need. This is preferred to #2 because of some oddities with asp.net page lifecycle.
These links come from somewhere, and that somewhere is usually a database or other reasonable datasource. So make it data driven — bind that datasource to a control like a repeater, gridview, details view, or similar. This is probably your best option.
If you want to generate controls dynamically & don't need to have those PostBack to the server (i.e. when a control is clicked/changed, it will come back to the same page) - you could use controls in System.Web.UI.HtmlControls namespace.
e.g.HtmlAnchor link = new HtmlAnchor();
link.href = "www.stackoverflow.com";
Page.Controls.Add(link);
Hope this gives you enough background.
EDIT: You can use the above code in a loop & replace the fixed value with what comes from a database/object.