Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > ASP .Net > ASP .Net Building Controls > DataGrid childcontrols problem

Reply
Thread Tools

DataGrid childcontrols problem

 
 
Richard Watt
Guest
Posts: n/a
 
      04-23-2004
Hi,

I am developing a custom control that inherits from the
datagrid. I want the normal functionality of the
Datagrid, then several buttons created underneath the
grid (not in the footer or pager).

In my basic example below I am creating a single button
in the overridden CreateChildControls. This compiles ok,
and when I use the control in a page, the grid renders
ok, but I do not see the button. I have played around
with overriding the render method, but everything I read
seems to indicate if you use CreateChildControls you
don't need to render.

What am I missing?

'-----------------------
Public Class MyGrid3
Inherits DataGrid

Dim btn As Button

Protected Overrides Sub CreateChildControls()

Controls.Clear()

btn = New Button
btn.Text = "button"
btn.ID = "btn1"
Controls.Add(btn)

MyBase.CreateChildControls()
End Sub

Public Overrides ReadOnly Property Controls() As
System.Web.UI.ControlCollection
Get
MyBase.EnsureChildControls()
Return MyBase.Controls
End Get
End Property
End Class


Cheers
Richard

 
Reply With Quote
 
 
 
 
Scott Mitchell [MVP]
Guest
Posts: n/a
 
      04-25-2004
Richard Watt wrote:
> I am developing a custom control that inherits from the
> datagrid. I want the normal functionality of the
> Datagrid, then several buttons created underneath the
> grid (not in the footer or pager).
>
> In my basic example below I am creating a single button
> in the overridden CreateChildControls. This compiles ok,
> and when I use the control in a page, the grid renders
> ok, but I do not see the button. I have played around
> with overriding the render method, but everything I read
> seems to indicate if you use CreateChildControls you
> don't need to render.
>
> What am I missing?


Well, your code looks like:

> Protected Overrides Sub CreateChildControls()
>
> Controls.Clear()
>
> btn = New Button
> btn.Text = "button"
> btn.ID = "btn1"
> Controls.Add(btn)
>
> MyBase.CreateChildControls()
> End Sub


And notice that you add your control and *then* call
CreateChildControls(). But... if you look at the CreateChildControls()
method for the DataGrid (using Reflector, for example), you'll see that
it's first line of code is:

base.Controls.Clear();


So the control(s) you add are cleared right off the bat! What you need
to do is call MyBase.CreateChildControls() and *then* add your
additional controls.

hth


--

Scott Mitchell
http://www.velocityreviews.com/forums/(E-Mail Removed)
http://www.4GuysFromRolla.com
http://www.ASPFAQs.com
http://www.ASPMessageboard.com

* When you think ASP, think 4GuysFromRolla.com!
 
Reply With Quote
 
 
 
 
Richard Watt
Guest
Posts: n/a
 
      04-25-2004
Thanks Scott

I have tried your sugestion and have changed
CreateChildControls() as shown below, but the result is
still the same - the grid shows but nothing else.

MyBase.CreateChildControls()

btn = New Button
btn.Text = "button"
btn.ID = "btn1"
Controls.Add(btn)


Cheers
Richard

>-----Original Message-----
>Richard Watt wrote:
>> I am developing a custom control that inherits from

the
>> datagrid. I want the normal functionality of the
>> Datagrid, then several buttons created underneath the
>> grid (not in the footer or pager).
>>
>> In my basic example below I am creating a single

button
>> in the overridden CreateChildControls. This compiles

ok,
>> and when I use the control in a page, the grid renders
>> ok, but I do not see the button. I have played around
>> with overriding the render method, but everything I

read
>> seems to indicate if you use CreateChildControls you
>> don't need to render.
>>
>> What am I missing?

>
>Well, your code looks like:
>
>> Protected Overrides Sub CreateChildControls()
>>
>> Controls.Clear()
>>
>> btn = New Button
>> btn.Text = "button"
>> btn.ID = "btn1"
>> Controls.Add(btn)
>>
>> MyBase.CreateChildControls()
>> End Sub

>
>And notice that you add your control and *then* call
>CreateChildControls(). But... if you look at the

CreateChildControls()
>method for the DataGrid (using Reflector, for example),

you'll see that
>it's first line of code is:
>
> base.Controls.Clear();
>
>
>So the control(s) you add are cleared right off the

bat! What you need
>to do is call MyBase.CreateChildControls() and *then*

add your
>additional controls.
>
>hth
>
>
>--
>
> Scott Mitchell
> (E-Mail Removed)
> http://www.4GuysFromRolla.com
> http://www.ASPFAQs.com
> http://www.ASPMessageboard.com
>
>* When you think ASP, think 4GuysFromRolla.com!
>.
>

 
Reply With Quote
 
Richard Watt
Guest
Posts: n/a
 
      04-26-2004
Scott

Your example works thanks. I broke down the rendering to
beginTag, contents and endTag and can get the button to
appear where I want it rather than on top of the grid.

However the problem I still have is that with a rendered
button I don't believe there is a way to capture server
side events within my control which I need to do.

Cheers
Richard

>-----Original Message-----
>
> The DataGrid is kind of tricky; internally it creates a

table and often it "forwards" method calls to that table;
try something like this (in this example I could just
output the string, but you can change the added control
to whatever control you want):
>
>public class MyDataGrid : DataGrid
> {
> private LiteralControl Lit;
> protected override void Render(HtmlTextWriter writer)
> {
> base.Render(writer);
> Lit.RenderControl(writer);
> }
>
> protected override void CreateChildControls()
> {
> base.CreateChildControls();
> Controls.Add((Lit = new LiteralControl("Hello")));
> }
> }
>
>Scott
> "Richard Watt" <rich_watt@NO-SPAM_hotmail.com> wrote

in message news:3f1901c42b12$c5832b10$(E-Mail Removed)...
> Thanks Scott
>
> I have tried your sugestion and have changed
> CreateChildControls() as shown below, but the result

is
> still the same - the grid shows but nothing else.
>
> MyBase.CreateChildControls()
>
> btn = New Button
> btn.Text = "button"
> btn.ID = "btn1"
> Controls.Add(btn)
>
>
> Cheers
> Richard
>
> >-----Original Message-----
> >Richard Watt wrote:
> >> I am developing a custom control that inherits from

> the
> >> datagrid. I want the normal functionality of the
> >> Datagrid, then several buttons created underneath

the
> >> grid (not in the footer or pager).
> >>
> >> In my basic example below I am creating a single

> button
> >> in the overridden CreateChildControls. This

compiles
> ok,
> >> and when I use the control in a page, the grid

renders
> >> ok, but I do not see the button. I have played

around
> >> with overriding the render method, but everything I

> read
> >> seems to indicate if you use CreateChildControls

you
> >> don't need to render.
> >>
> >> What am I missing?

> >
> >Well, your code looks like:
> >
> >> Protected Overrides Sub CreateChildControls()
> >>
> >> Controls.Clear()
> >>
> >> btn = New Button
> >> btn.Text = "button"
> >> btn.ID = "btn1"
> >> Controls.Add(btn)
> >>
> >> MyBase.CreateChildControls()
> >> End Sub

> >
> >And notice that you add your control and *then* call
> >CreateChildControls(). But... if you look at the

> CreateChildControls()
> >method for the DataGrid (using Reflector, for

example),
> you'll see that
> >it's first line of code is:
> >
> > base.Controls.Clear();
> >
> >
> >So the control(s) you add are cleared right off the

> bat! What you need
> >to do is call MyBase.CreateChildControls() and *then*

> add your
> >additional controls.
> >
> >hth
> >
> >
> >--
> >
> > Scott Mitchell
> > (E-Mail Removed)
> > http://www.4GuysFromRolla.com
> > http://www.ASPFAQs.com
> > http://www.ASPMessageboard.com
> >
> >* When you think ASP, think 4GuysFromRolla.com!
> >.
> >

 
Reply With Quote
 
Richard Watt
Guest
Posts: n/a
 
      04-27-2004
Scott

The original problem I posted with the child control not
appearing seems to be related to DataBind(). The control
would actually appear (without the need for render) upon
a postback where the grid was not rebound to the data.
Looking at the code in the debugger, the button is in the
control collection, but then disappears after the
DataBind. I tried overriding DataBind so it called
EnsureChildControls after the base DataBind was called,
hoping this would fix it, but it did not work.

I have a solution where I override DataBind, call the
base class DataBind then create the button control. This
works but for reasons I cannot explain looses the
viewstate so the grid needs to DataBind for every
postback. From another thread I recall that creating
your controls anywhere except in CreateChildControl is
not considered good practice, so this is not an ideal
solution, but may have to do for now.

Thanks for your help.

Cheers
Richard

>-----Original Message-----
>
> As long as you get the button into the control

heirarchy you should be able to capture the events for
the button; in the example I had, a button created in the
CreateChildControls should be able to be an event target
(try adding an event handler in CreateChildControls and
see what happens).
>
>Scott
> "Richard Watt" <rich_watt@NO-SPAM_hotmail.com> wrote

in message news:414001c42b24$02e314f0$(E-Mail Removed)...
> Scott
>
> Your example works thanks. I broke down the rendering

to
> beginTag, contents and endTag and can get the button

to
> appear where I want it rather than on top of the grid.
>
> However the problem I still have is that with a

rendered
> button I don't believe there is a way to capture

server
> side events within my control which I need to do.
>
> Cheers
> Richard
>
> >-----Original Message-----
> >
> > The DataGrid is kind of tricky; internally it

creates a
> table and often it "forwards" method calls to that

table;
> try something like this (in this example I could just
> output the string, but you can change the added

control
> to whatever control you want):
> >
> >public class MyDataGrid : DataGrid
> > {
> > private LiteralControl Lit;
> > protected override void Render(HtmlTextWriter

writer)
> > {
> > base.Render(writer);
> > Lit.RenderControl(writer);
> > }
> >
> > protected override void CreateChildControls()
> > {
> > base.CreateChildControls();
> > Controls.Add((Lit = new LiteralControl("Hello")));
> > }
> > }
> >
> >Scott
> > "Richard Watt" <rich_watt@NO-SPAM_hotmail.com>

wrote
> in message news:3f1901c42b12$c5832b10

$(E-Mail Removed)...
> > Thanks Scott
> >
> > I have tried your sugestion and have changed
> > CreateChildControls() as shown below, but the

result
> is
> > still the same - the grid shows but nothing else.
> >
> > MyBase.CreateChildControls()
> >
> > btn = New Button
> > btn.Text = "button"
> > btn.ID = "btn1"
> > Controls.Add(btn)
> >
> >
> > Cheers
> > Richard
> >
> > >-----Original Message-----
> > >Richard Watt wrote:
> > >> I am developing a custom control that inherits

from
> > the
> > >> datagrid. I want the normal functionality of the
> > >> Datagrid, then several buttons created

underneath
> the
> > >> grid (not in the footer or pager).
> > >>
> > >> In my basic example below I am creating a single

> > button
> > >> in the overridden CreateChildControls. This

> compiles
> > ok,
> > >> and when I use the control in a page, the grid

> renders
> > >> ok, but I do not see the button. I have played

> around
> > >> with overriding the render method, but

everything I
> > read
> > >> seems to indicate if you use CreateChildControls

> you
> > >> don't need to render.
> > >>
> > >> What am I missing?
> > >
> > >Well, your code looks like:
> > >
> > >> Protected Overrides Sub CreateChildControls()
> > >>
> > >> Controls.Clear()
> > >>
> > >> btn = New Button
> > >> btn.Text = "button"
> > >> btn.ID = "btn1"
> > >> Controls.Add(btn)
> > >>
> > >> MyBase.CreateChildControls()
> > >> End Sub
> > >
> > >And notice that you add your control and *then*

call
> > >CreateChildControls(). But... if you look at the

> > CreateChildControls()
> > >method for the DataGrid (using Reflector, for

> example),
> > you'll see that
> > >it's first line of code is:
> > >
> > > base.Controls.Clear();
> > >
> > >
> > >So the control(s) you add are cleared right off

the
> > bat! What you need
> > >to do is call MyBase.CreateChildControls() and

*then*
> > add your
> > >additional controls.
> > >
> > >hth
> > >
> > >
> > >--
> > >
> > > Scott Mitchell
> > > (E-Mail Removed)
> > > http://www.4GuysFromRolla.com
> > > http://www.ASPFAQs.com
> > > http://www.ASPMessageboard.com
> > >
> > >* When you think ASP, think 4GuysFromRolla.com!
> > >.
> > >

 
Reply With Quote
 
Guest
Posts: n/a
 
      04-27-2004
Scott - you're a genius!! Thanks for sticking with me.
I now have it working with the ViewState.

I have posted my demo class code for the benefit of
others. I did quite of bit of searching in newsgroups
and articles and never found anything demonstrating quite
what I was trying to do.


public class NewDataGrid : DataGrid
{
Button btn;

protected override void Render(HtmlTextWriter
writer) {
//if don't override this method, the child
controls are rendered
//outside of the <table> tags, and will
therefore just appear at top
//of the page.
//RenderBeginTag & RenderEndTag wrap
everything inside a <DIV> tag so
//children controls rendered underneath the
<table>

base.RenderBeginTag(writer);
base.RenderContents(writer);
base.RenderEndTag(writer);
}

void CreateControlButtons() {
btn = new Button();
btn.Text = "button";
btn.ID = "btn1";
btn.Click += new System.EventHandler
(this.btn_Click);
this.Controls.Add(btn);
}

protected override void CreateChildControls() {
base.CreateChildControls();
CreateControlButtons();
}

private void btn_Click(object sender,
System.EventArgs e) {
base.BackColor= Color.AntiqueWhite;
}

//not sure if actually need to override this or
not.
//Works ok without it so far but some samples
recomend its use.
public override ControlCollection Controls {
get {
base.EnsureChildControls();
return base.Controls;
}
}

public override void DataBind() {
base.DataBind();
CreateControlButtons();
}
}

Cheers
Richard

>-----Original Message-----
>
> Ah, yes you are on to something, this is coming back to

me now; for data bound controls the DataBind method will
typically do a Controls.Clear() and then create the
underlying controls (and the DataBind will set
ChildControlsCreated = true, which means that calls to
EnsureChildControls will skip the call to
CreateChildControls()).
>
> For a DataGrid, one usually binds the grid which in

turns creates the control hiearchy. Now, on postback, one
might skip the DataBind on the grid, so the DataGrid
CreateChildControls must be able to recreate the control
heirarchy using the ViewState (thus the
CreateChildControls is called as an alternate to the
DataBind -- kind-a-sorta).
>
> So, you need to create a common-method/code-block that

both DataBind and CreateChildControls can call to get you
control built -- something like:
>
>public override void DataBind() {
> base.DataBind(); // this will call Controls.Clear()

so do it first
> MyCreateButton();
> }
>
> protected override void CreateChildControls() {
> base.CreateChildControls(); // again, this will call

Controls.Clear() so do it first.
> MyCreateButton();
> }
>
> Yes, using CreateChildControls is the pattern method

to follow when creating your own composite controls; but
in your case you are really enhancing the DataGrid and
so, doing what you've done -- or, like in the above two
methods -- is the right approach.
>
>Scott
>


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
ChildControls state mauricio ASP .Net 1 03-11-2008 03:23 PM
Events don't fire in control with identical childcontrols Nico ASP .Net Web Controls 0 08-21-2007 08:59 AM
ChildControls and ViewState Graham ASP .Net 1 09-06-2005 12:19 PM
ChildControls disappear after Clicking Sandy ASP .Net Web Controls 0 08-12-2005 07:48 AM
Rendered control vs childcontrols Peter ASP .Net Web Controls 0 05-01-2005 11:19 AM



Advertisments