views:

290

answers:

3

I'm creating a custom control for a group of peers and I'm running into a road block. The purpose of the control is to provide an easy way to implement grids with nesting, sorting, etc.

To create the nesting, I have a child GridView that serves as a blueprint for the rest of the children. I allow the developer to configure it how they want and then the custom control makes a number of identical copies.

My problem here is that I can't perfectly copy the child grids. MemberWiseClone() doesn't seem to work and GridView isn't serializable.

My current solution is to manually copy over a list of fields that I know we'll need (ID, CssClass, etc) but that's clearly inadequate and doesn't even touch EventHandlers.

Is there a good way to deep copy a GridView --or-- provide the functionality I've described using another method?

A: 

Can you use viewstate or controlstate? A gridview can be saved to and restored from viewstate. If you can convert the control to a viewstate string, then restore it to a new gridview object, then change the object ID, this may provide you a mechanism. You may want to look at IStateFormatter

This won't handle event handlers, though. However, the benefit of this approach is that we know it works for saving and restoring everything else.

Steve Cooper
A: 

If all you need is a snapshot of the GridView's html in another setting, then you can get the rendered html using the RenderControl method.

Here's an example:

http://forums.asp.net/p/1016960/1368933.aspx

System.IO.StringWriter stringWriter = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter htmlWriter = new System.Web.UI.HtmlTextWriter(stringWriter);
gridView.RenderControl(htmlWriter);
string s = stringWriter.ToString();

This doesn't solve the EventHandler issue, though.

Doug
A: 

Don't forget that we are in an object oriented language. I think you need to make your control by inheriting from the BoundField and GridView objects. You can override the GridView's CreateColumns function and have it use your new BoundField object instead of the default.

This is how I created a multi-column TreeView from the GridView, see here.

The BoundFiled object has events that you can override like New, InitializeDataCell, OnDataBindField, ExtractValuesFromCell, or make your own. You can add events handlers like:

 Protected Overrides Sub InitializeDataCell(ByVal cell As
 System.Web.UI.WebControls.DataControlFieldCell, 
 ByVal rowState As System.Web.UI.WebControls.DataControlRowState)
    ... ect...
                AddHandler cell.DataBinding, AddressOf OnDataBindField

            End Sub

Inheriting from the GridView gives you a lot of methods that you can override that will give you total control of what your new object can do. These include OnInit, InitializeRow, PerformDataBinding, OnPreRender, OnSorting, UpdateRow, InitializeDataCell, etc. You can see how you would have total control.

If you are going to go down this road, I would highly recommend the following book. He uses the GridView in his example.

alt text

JBrooks
This isn't quite what I was looking for but I think my initial desires were a little misguided. I have since solved my own problem using a different methodology but this was the closest response to being right. Thanks.
beardog