DataGrid childcontrols problem

Discussion in 'ASP .Net Building Controls' started by Richard Watt, Apr 23, 2004.

  1. Richard Watt

    Richard Watt Guest

    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
     
    Richard Watt, Apr 23, 2004
    #1
    1. Advertising

  2. 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.4GuysFromRolla.com
    http://www.ASPFAQs.com
    http://www.ASPMessageboard.com

    * When you think ASP, think 4GuysFromRolla.com!
     
    Scott Mitchell [MVP], Apr 25, 2004
    #2
    1. Advertising

  3. Richard Watt

    Richard Watt Guest

    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
    >
    > http://www.4GuysFromRolla.com
    > http://www.ASPFAQs.com
    > http://www.ASPMessageboard.com
    >
    >* When you think ASP, think 4GuysFromRolla.com!
    >.
    >
     
    Richard Watt, Apr 25, 2004
    #3
  4. Richard Watt

    Richard Watt Guest

    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$...
    > 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
    > >
    > > http://www.4GuysFromRolla.com
    > > http://www.ASPFAQs.com
    > > http://www.ASPMessageboard.com
    > >
    > >* When you think ASP, think 4GuysFromRolla.com!
    > >.
    > >
     
    Richard Watt, Apr 26, 2004
    #4
  5. Richard Watt

    Richard Watt Guest

    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$...
    > 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

    $...
    > > 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
    > > >
    > > > http://www.4GuysFromRolla.com
    > > > http://www.ASPFAQs.com
    > > > http://www.ASPMessageboard.com
    > > >
    > > >* When you think ASP, think 4GuysFromRolla.com!
    > > >.
    > > >
     
    Richard Watt, Apr 27, 2004
    #5
  6. Richard Watt

    Guest Guest

    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
    >
     
    Guest, Apr 27, 2004
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Graham

    ChildControls and ViewState

    Graham, Sep 6, 2005, in forum: ASP .Net
    Replies:
    1
    Views:
    565
    =?Utf-8?B?SnVsaWFuIEplbGZz?=
    Sep 6, 2005
  2. mauricio

    ChildControls state

    mauricio, Mar 11, 2008, in forum: ASP .Net
    Replies:
    1
    Views:
    300
    bruce barker
    Mar 11, 2008
  3. Peter

    Rendered control vs childcontrols

    Peter, May 1, 2005, in forum: ASP .Net Web Controls
    Replies:
    0
    Views:
    135
    Peter
    May 1, 2005
  4. Sandy

    ChildControls disappear after Clicking

    Sandy, Aug 12, 2005, in forum: ASP .Net Web Controls
    Replies:
    0
    Views:
    122
    Sandy
    Aug 12, 2005
  5. Nico
    Replies:
    0
    Views:
    137
Loading...

Share This Page