Link to home
Start Free TrialLog in
Avatar of PaulHews
PaulHewsFlag for Canada

asked on

Server control designer - change width of child controls

I have a server control that inherits from System.Web.UI.WebControls.CompositeControl.  It contains a panel which contains some child controls.
I've also created a simple designer and applied the Designer metatag to the Composite control, so the definitions look like this:

<Designer(GetType(SiteSearchDesigner)), _
 ToolboxData("<{0}:SiteSearch runat=""server""></{0}:SiteSearch>"), _
 Serializable()> _
Public Class SiteSearch
    Inherits System.Web.UI.WebControls.CompositeControl
    Implements INamingContainer

'Custom properties plus CreateChildControls override.

End Class  

Public Class SiteSearchDesigner
    Inherits System.Web.UI.Design.WebControls.CompositeControlDesigner
'Right now this class is empty.
End Class

I have the icon in my toolbox, I can add it to a form and the control displays okay.  I can resize the width in design mode, and the panel resizes (but not the child controls.)

I can resize the height, but the panel height doesn't change.

How do I make the panel resize in height?
How do I go about making the child controls resize according to the width of the panel?
Avatar of Bob Learned
Bob Learned
Flag of United States of America image

My take on this is to just inherit from WebControl, and generate the necessary controls via HTML code.

You can override the RenderContents method, and generate the HTML using controls:

Protected Overrides Sub RenderContents(ByVal writer As HtmlTextWriter)

Dim panel As New Panel()
panel.ID = Me.ID
panel.Height = Me.Height
panel.Width = Me.Width

For Each key As String In Me.Style.Keys
   panel.Style(key) = Me.Style(key)
Next key

Dim label As New Label()
label.ID = "lbl"
label.Text = "Contact"

panel.Controls.Add(label)

panel.RenderControl(writer)

End Sub

Bob
Avatar of PaulHews

ASKER

Is it possible to attach events to the child controls this way?  I'm not having much luck with this simple example getting the buttonclicked event to fire.

I'm also not seeing the blue border on the new panel.  
The width of the label seems to remain default.


Public Class TestControl
    Inherits WebControl
    Protected Overrides Sub RenderContents(ByVal writer As HtmlTextWriter)

        Dim panel As New Panel()
        panel.ID = Me.ID
        panel.Height = Me.Height
        panel.Width = Me.Width
        panel.BorderStyle = WebControls.BorderStyle.Solid
        panel.BorderColor = Drawing.Color.Blue
        panel.BorderWidth = New Unit(3)

        'For Each key As String In Me.Style.Keys
        '    panel.Style(key) = Me.Style(key)
        'Next key

        Dim label As New Label()
        label.ID = "lbl"
        label.Text = "Contact"
        label.Width = panel.Width
        panel.Controls.Add(label)

        Dim button As New Button
        button.ID = "button"
        button.Text = "push me"
        AddHandler button.Click, AddressOf ButtonClicked
        panel.Controls.Add(button)

        panel.RenderControl(writer)

    End Sub

    Private Sub ButtonClicked(ByVal sender As Object, ByVal e As EventArgs)
        Dim lbl As Label = DirectCast(Me.FindControl("lbl"), Label)

    End Sub
End Class
You commented these lines out:

       'For Each key As String In Me.Style.Keys
        '    panel.Style(key) = Me.Style(key)
        'Next key

The style properties for the control aren't getting set on the panel.  I would set the width for the Label = 100%.  When the page renders in the browser, does it have a __doPostBack reference for the button?

Bob
Okay... I set up a new test web site, added a web control library to the solution, added the class above to the library, and now it at least shows the panel border, and sizes the label to the width of the panel...  Still no love with the button event.  Here's how the button HTML renders.

<input type="submit" name="button" value="push me" id="button" />
Bob, I don't think that it's going to work.  It doesn't appear that child controls created this way get added to the control tree, as far as I can see.  Which means going back to inheriting from CompositeControl, since controls created in CreateChildControls can definitely receive events.  But please let me know if you have other thoughts.  The documentation isn't the clearest, and I feel a bit like I'm inventing the wheel, since I can't find any samples out there that use the designer class in a non-trivial way.
This is what I've got working for me....  The key was to figure out how to get at the instance of the control from the designer.  Now the child controls resize themselves as I drag the sides of the control.  Consider it solved.

Public Class SiteSearchDesigner
    Inherits System.Web.UI.Design.WebControls.CompositeControlDesigner
    Private mInstance As SiteSearch
    Public Overrides Sub Initialize(ByVal component As System.ComponentModel.IComponent)
        mInstance = CType(component, SiteSearch)
        MyBase.Initialize(component)
    End Sub
    Public Overrides Function GetDesignTimeHtml() As String
        Dim sw As New System.IO.StringWriter
        Dim hw As New HtmlTextWriter(sw)
        Try
            Dim Panel As New WebControls.Panel
            Panel.ID = "SiteSearchPanel"
            Panel.Width = mInstance.Width
            Panel.Height = mInstance.Height
            Panel.GroupingText = "Enter some of the site name to search"
            Panel.DefaultButton = "cmdSearch"


            Dim txtFilter As New System.Web.UI.WebControls.TextBox
            txtFilter.ID = "txtFilter"
            txtFilter.AutoPostBack = True
            txtFilter.Width = New Unit(Panel.Width.Value - 40)
            txtFilter.Height = New Unit(16)

            Panel.Controls.Add(txtFilter)
            Panel.Controls.Add(New LiteralControl(" "))
            Dim cmdSearch As New System.Web.UI.WebControls.ImageButton
            cmdSearch.ID = "cmdSearch"
            cmdSearch.ImageUrl = "~/images/searchbutton.gif"
            cmdSearch.Height = New Unit(16)
            cmdSearch.Width = New Unit(16)
            Panel.Controls.Add(cmdSearch)

            Panel.Controls.Add(cboSite)
            Panel.RenderControl(hw)
        Catch ex As Exception
            MsgBox(ex.ToString)
        End Try

        Return sw.ToString


    End Function

End Class
ASKER CERTIFIED SOLUTION
Avatar of Vee_Mod
Vee_Mod
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial