all groups > asp.net building controls > february 2007 >
You're in the

asp.net building controls

group:

GridView DataBind() Not Working


GridView DataBind() Not Working Mark Olbert
2/16/2007 9:43:12 PM
asp.net building controls:
I have a GridView as a child control in a custom composite control which is stubornly refusing to databind at design time. I'm
convinced I must be missing something about how the databinding process works differently at design time.

Here is the code that constructs the GridView in CreateChildControls():

gridSearch = new GridView();

gridSearch.AutoGenerateColumns = true;

CommandField cmdField = new CommandField();
cmdField.ShowSelectButton = false;
cmdField.SelectText = "select";
gridSearch.Columns.Add(cmdField);

FieldInfoCollection fieldColl = DesignMode ? DummyData.Fields : SearchFields;

for( int idx = 0; idx < fieldColl.Count; idx++ )
{
BoundField curField = new BoundField();

curField.HeaderText = fieldColl[idx].Friendly;
curField.DataField = fieldColl[idx].FieldName;
curField.ReadOnly = true;
curField.ShowHeader = true;
curField.Visible = true;

gridSearch.Columns.Add(curField);
}

At design time DummyData.Fields is composed of five "rows" of data in a List<>, where each row is a simple object:

public class DummyDataItem
{
private int row = 0;

public DummyDataItem( int row )
{
this.row = row;
}

protected string FieldValue( int row, int col )
{
return String.Format("Field{0}_Row{1}", col, row);
}

public string Field1
{
get { return FieldValue(row, 1); }
}

public string Field2
{
get { return FieldValue(row, 2); }
}

public string Field3
{
get { return FieldValue(row, 3); }
}
}

DummyData.Fields simply returns a list that has FieldNames of Field1, Field2 and Field3, corresponding to the properties in
DummyDataItem.

Later on the composite control that contains the GridView has its DataSource property set to that List<> of DummyDataItems, and then
the following code gets called in an event handler:

gridSearch.DataSource = DataSource;
gridSearch.DataBind();

No rows are created. No exceptions are thrown. I can walk over the code in the debugger, so I know the event handler is being
triggered. I verified that the gridSearch, at the point of the DataBind() call, has columns with DataField properties equal to
Field1, Field2 and Field3.

Yet it doesn't work. How could this be any simpler? Do GridViews not work with List<> of objects exposing public string properties?

I would appreciate some advice or suggestions.

RE: GridView DataBind() Not Working stcheng NO[at]SPAM online.microsoft.com
2/19/2007 12:53:30 PM
Hello Mark,

From your description, you're developing an ASP.NET custom web control
which contains a child Gridview control. However, you're getting difficulty
when try rendering the custom control in design-view, the gridview does not
display, correct?

Based on my experience, for ASP.NET custom webcontrol, it would preferred
that we separate the design-time rendering code from runtime code as much
as possible. And normally there would exists a ControlDesigner associated
with a given webcontrol and provide the "GetDesignTimeHtml" that do the
design-time rendering task. For your scenario, you've added a chld
GridView in your custom web control, then how do you assign the datasource
and perform the databinding on the child gridview? I haven't found the
related code in code snippet you attached. I assume you've exposed a top
level property on your custom control to accept the DataSource, and make
the custom control's DataBind method to trigger the child GridView's
DataBinding, correct?

I think the problem that GridView not display may caused by the databinding
is not correctly performed at the design-time rendering stage, I'll try
performing some tests on my side to see whether I can get it work with the
control designer interface. I'll update you as soon as possible. Also, if
there is anything I missed above, please feel free to inform me.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead



==================================================

Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.



Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.

==================================================



This posting is provided "AS IS" with no warranties, and confers no rights.
Re: GridView DataBind() Not Working Mark Olbert
2/19/2007 11:06:32 PM
Steven,

Thanks for looking into this. I'm interested in hearing what you come up with.

I have continued to struggle with this problem (I think I'm now up to the 20th different approach, which involves replicating a lot
of the functionality of the Wizard control because, unfortunately, some of the key classes I'd like to utilize, like the WizardSteps
ControlBuilder, are sealed).

This GridView problem is a real puzzler, however. I've tried approaches where the custom control it's created within is a databound
control, and approaches where it isnt', without any success.

The thing I find most confusing, though, is that, regardless of the type of control on which it's hosted (i.e., regardless of
whether or not the hosting control is a databound control or not), even these code snippets fail (all this stuff would be in the
custom control hosting the GridView):

public class SomeCustomControl : <either DataBoundCompositeControl or CompositeControl>
{
private GridView theGrid;

protected override void CreateChildControls()
{
...
theGrid = new GridView();
Controls.Add(theGrid);
...
}

protected override void OnInit( EventArgs e )
{
base.OnInit(e);

theGrid.DataSource = <some dummy data source>;
theGrid.DataBind(); // fails; no rows created, no exceptions thrown
}

protected override RenderControl( HtmlWriter writer )
{
theGrid.DataSource = <some dummy data source>;
theGrid.DataBind(); // fails; no rows created, no exceptions thrown

base.RenderControl(writer);
}

...
}

I tried sticking that test code into OnInit and RenderControl because I read somewhere that, at design-time, the control life-cycle
is "abbreviated", and only the OnInit and Rendering phases get executed (i.e., no OnLoad()).

But why wouldn't the DataBind() in either of those handlers work? I know that I could run into problems with persistance if I bind
too late, but for the test I don't care if the rows "disappear" later -- I just want to see them created. And they never get
created!

I keep thinking that maybe there's something wrong with my dummy data source, but all it is is five objects in a list, where each
object has three properties (Field1, Field2, and Field3)...and I've verified that, at the point of the DataBind(), the GridView has
three columns with DataField values of Field1, Field2 and Field3. So I dont' see how the data could be a problem.

I've also created some dummy derived GridView classes that don't add any functionality to the GridView:

[Designer(MyGridViewDesigner)]
public class MyGridView : GridView
{
}

I overrode a bunch of methods in MyGridViewDesigner (but added no new functionality), and then put an instance of MyGridView on a
test web page so I could watch how the design-time databinding takes place -- it works fine (i.e., dummy rows and columns get
displayed), and I can see where the designer methods get called. But then using MyGridView in my composite control leads
to...nothing again. No calls to the designer methods. No dummy data displayed.

So the GridView is behaving differently depending upon whether it's instantiated on a webpage at design time, or within a custom
control that, in turn, is instantiated at design time. Why in the world should that happen?

I look forward to hearing what you come up with.

- Mark

Re: GridView DataBind() Not Working stcheng NO[at]SPAM online.microsoft.com
2/21/2007 12:00:00 AM
Thanks for your reply Mark,

yes, based on my research, if you completely add the rendering code
logic(both for runtime and design-time) in your control's
code(CreateChildcontrols), the designer (of your toplevel custom control)
will not render the child GridView. Also, as you discussed in another
thread with my colleague Walter, for child controls added into top custom
control's controls collection, it hasn't a designer associated like the top
level control.

Currently, what I'm still trying is use our own custom control designer and
render the control (and its child controls) manually. And I've got the
following result so far:

*in our custom control designer, we can create a new instance of our custom
control type and render it(or you can set some additional attributes on it)
e.g.

=================================
[DefaultProperty("Text")]
[ToolboxData("<{0}:MyComposite runat=server></{0}:MyComposite>")]
[Designer(typeof(MyCompositeDesigner))]
public class MyComposite : CompositeControl
{
Label _label;
GridView _grid;


[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")]
[Localizable(true)]
public string Text
{
get
{
String s = (String)ViewState["Text"];
return ((s == null) ? String.Empty : s);
}

set
{
ViewState["Text"] = value;
}
}



protected override void CreateChildControls()
{
Controls.Clear();

_label = new Label();
_label.ID = "lblMessage";
Controls.Add(_label);

_label.Text = Text;

_grid = new GridView();
_grid.ID = "gvData";
Controls.Add(_grid);

_grid.AutoGenerateColumns = true;

_grid.DataSource = HelperUtil.GetDummyListItems();
_grid.DataBind();


}




}

internal class HelperUtil
{
internal static ListItem[] GetDummyListItems()
{
ListItem[] items = new ListItem[5];
for (int i = 0; i < items.Length; i++)
{
items[i] = new ListItem("key" + i, "value" + i);
}

return items;
}
}

internal class MyCompositeDesigner : CompositeControlDesigner
{

public override string GetDesignTimeHtml()
{
string html = string.Empty;

MyCompositeControl mc1 = new MyCompositeControl();


ICompositeControlDesignerAccessor accessor = mc1 as
ICompositeControlDesignerAccessor;

accessor.RecreateChildControls();



StringWriter sw = new StringWriter();
XhtmlTextWriter hw = new XhtmlTextWriter(sw);

mc1.RenderControl(hw);

html+= sw.ToString();


return html;
}
}
==========================

However, if I try using the control instance from the designer's
"ViewControl" property to render, the child GridView always not display.
e.g.
======================
public override string GetDesignTimeHtml()
{
string html = string.Empty;



WebControl mc1 = new MyComposite();

mc1 = this.ViewControl as WebControl;


ICompositeControlDesignerAccessor accessor = mc1 as
ICompositeControlDesignerAccessor;

accessor.RecreateChildControls();




StringWriter sw = new StringWriter();
XhtmlTextWriter hw = new XhtmlTextWriter(sw);

mc1.RenderControl(hw);

html+= sw.ToString();


return html;
}
=======================

I will do some further research on this to see whether it does be not
supported to use the original instance for manual rendering in designer or
if there is any other means. Anyway, at least you can do custom rendering
in custom control designer by manually creating a control instance. I'll
update you when I get any progress at the earliest time.


Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead



This posting is provided "AS IS" with no warranties, and confers no rights.



Re: GridView DataBind() Not Working Mark Olbert
2/21/2007 7:09:18 AM
Steven,

Thanks for the research. I await further results.

What do you mean by "...at least you can do custom rendering in custom control designer by manually creating a control instance"? Do
you mean to create a dummy GridView and slip it into the Controls collection for the control being designed? Or into the render
stream for GetDesignTimeHtml()?

- Mark

[quoted text, click to view]
Re: GridView DataBind() Not Working stcheng NO[at]SPAM online.microsoft.com
2/22/2007 1:18:49 PM
Hi Mark,

I mean completely create a new instance of the custom control type in
Designer's GetDesignTimeHtml method and render it manually. e.g.

==========================

public override string GetDesignTimeHtml()
{
string html = string.Empty;

MyCompositeControl mc1 = new MyCompositeControl();

ICompositeControlDesignerAccessor accessor = mc1 as
ICompositeControlDesignerAccessor;

accessor.RecreateChildControls();

StringWriter sw = new StringWriter();
XhtmlTextWriter hw = new XhtmlTextWriter(sw);

mc1.RenderControl(hw);

html+= sw.ToString();

return html;
}
==============================

I'll update you for any new information on this.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no rights.
Re: GridView DataBind() Not Working stcheng NO[at]SPAM online.microsoft.com
2/27/2007 2:03:04 AM
Hi Mark,

Just inform you that I'm still working on this. So far I still haven't been
able to make the designer automatically render out the child nested
Gridview in designer view. I'll perform some further research.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no rights.
Re: GridView DataBind() Not Working stcheng NO[at]SPAM online.microsoft.com
2/28/2007 1:38:12 PM
Hi Mark,

After some further investigation and discussing with some other engineers.
I've found the cause of the problem. Actually, it is related to our
control's creation code in "CreaetChildControls" method(I have pasted my
modified test control which works at design-time). The problem is that we
need to add the child controls into parent container control after they
have been initialized(or databound). For example,

You should first create the GridView, and set the certain properties on it,
bind it with data, after all those operations, you add it into parent
container's controls collection. If you add it into parent container right
after you create it, then, the designer won't render out the changes you
did later. I think this behavior is due to the internal rendering
mechanism of designer.



===complete test control====
namespace WebControlLib
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:MyComposite runat=server></{0}:MyComposite>")]
public class MyComposite : CompositeControl
{
Label _label;
GridView _grid;

[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")]
[Localizable(true)]
public string Text
{
get
{
String s = (String)ViewState["Text"];
return ((s == null) ? String.Empty : s);
}
set
{
ViewState["Text"] = value;
}
}

protected override void CreateChildControls()
{
Controls.Clear();

_label = new Label();
_label.ID = "lblMessage";
_label.Text = Text;

_grid = new GridView();
_grid.ID = "gvData";

_grid.AutoGenerateColumns = true;

if (DesignMode)
{
_grid.DataSource = HelperUtil.GetDummyListItems();
_grid.DataBind();
}

Controls.Add(_label);
Controls.Add(_grid);

}
}

internal class HelperUtil
{
internal static ListItem[] GetDummyListItems()
{
ListItem[] items = new ListItem[5];
for (int i = 0; i < items.Length; i++)
{
items[i] = new ListItem("key" + i, "value" + i);
}
return items;
}
}
}
=================================


Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead



This posting is provided "AS IS" with no warranties, and confers no rights.
Re: GridView DataBind() Not Working Mark Olbert
2/28/2007 2:12:01 PM
Steven,

Thanx for digging into the issue. That's effectively what I'm doing now.

I hope you share with your engineers the notion that it's really not a good idea to have code execute methods like DataBind() on a
datasource...and have nothing happen. >>Something<< has to happen, even if it's just an exception!

- Mark

[quoted text, click to view]
Re: GridView DataBind() Not Working Dan Rausch
2/28/2007 11:16:12 PM
I am having a slightly different problem trying to use a gridview in a
composite control. If I set the AutoGenerateColumns = True, everything
works fine. However, I want to control the columns that are displayed,
so I want to set AutoGenerateColumns = False. I then create several
BoundField objects that I add to the columns collection. The problem
is, no columns show up at all. Is there something else that I have to
do to have it generate the columns using my Columns collection? An
abbreviated code snippet from my CreateChildControls function is as
follows:

gv.ID = "gv"
gv.AutoGenerateColumns = False
gv.DataKeyNames = strDataKeyNames
gv.DataSource = CoreCategoryLookupTable
gv.DataBind()

Dim objBoundField As BoundField
objBoundField = New BoundField
objBoundField.DataField = "Category1"
objBoundField.HeaderText = "Category 1"
gv.Columns.Add(objBoundField)
Me.Controls.Add(gv)

Any help that you can give would be very much appreciated.

Thank you.

Re: GridView DataBind() Not Working stcheng NO[at]SPAM online.microsoft.com
3/1/2007 1:09:04 AM
Thanks for your reply Mark,

Glad that you've also found that. Sure, I'll take care of the datasource
issue, and also recommend you submit this to our product feedback center so
that the product team and also get awared of this:

http://connect.microsoft.com/feedback/default.aspx?SiteID=210

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no rights.
AddThis Social Bookmark Button