Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Convert a Usercontrol to a WebControl

0.00/5 (No votes)
10 Aug 2004 1  
You've created a beautiful usercontrol with HTML layout but you want to use it as a Server Control. This macro generates the instantiation and render code for you.

Introduction

Ever written a nice usercontrol and wanted to migrate it to a webcontrol? Then you'll know you have to write a lot of render and initialization stuff yourself. With this macro, some of it is generated out of the .ascx file you created.

For instance, if you have this code:

Ascx Code

Then this macro will output the following lines to the output window:

Resulting output

Then all you have to do is copy the code to the codebehind file, change the inherit, and presto, a webcontrol.

The macro:

Sub GenerateWebcontrolCode()
    Dim str As String = ""
    Dim createCC As String = ""
    Dim renderCC As String = ""
    Dim attribsCC As String = ""
    Dim selection As TextSelection = DTE.ActiveDocument.Selection()
    selection.SelectAll()
    Dim theText As String = selection.Text

    'all <asp:Label like tags and id's

    Dim r As New Regex("\<(?<tag>\w*):(?<type>\w*)" & _
      "(.\n?)*?id=\""?(?<id>\w*)\""?(.\n?)*?>", RegexOptions.IgnoreCase)
    Dim matches As MatchCollection = r.Matches(theText)
    Dim m As Match

    'set the startindex to position after the last <%@ register tag!!
    Dim startindex As Integer = 0
    Dim matchRegistertags As Match = Regex.Match(theText, _
                     "<%@.*?>", RegexOptions.RightToLeft)
    startindex = matchRegistertags.Index + matchRegistertags.Length
    If (startindex < 0) Then
        startindex = 0
    End If

    For Each m In matches
        'only start again after endtag (templated controls will not work!!)
        If m.Index > startindex Then

            Dim tp As String = m.Groups("type").Value
            Dim id As String = m.Groups("id").Value
            Dim tag As String = m.Groups("tag").Value

            'the stuff for the render override
            'Get the html in before the control 
            'and write this to the HTMLwriter
            Dim htmlstr As String = _
              theText.Substring(startindex, m.Index - startindex)
            htmlstr = htmlstr.Replace("""", """""")
            renderCC += "writer.Write(@""" + htmlstr + """);" + vbCrLf
            renderCC += id + ".RenderControl(writer);" + vbCrLf

            'Set the index to the position of the endtag (if available, 
            'otherwise control is closed with />
            startindex = m.Index + m.Length
            Dim endtag As String = "</" + tag + ":" + tp + ">"
            Dim inext2 As Integer = theText.IndexOf(endtag, startindex)
            If inext2 <> -1 Then
                startindex = inext2 + endtag.Length
            End If

            ' the stuff for the init procedures make sure you add this to 
            createCC += id + " = new " + tp + "();" + vbCrLf

            'Add attributes to the object.
            'Only attibutes assigned within the first tag no 
            'templated controls or default properties are set
            Dim r2 As New Regex("(?<prop>\w*)=\""?(?<value>\w*)\""?", _
                                                RegexOptions.IgnoreCase)
            Dim ms2 As MatchCollection = r2.Matches(m.Value)
            Dim m2 As Match
            For Each m2 In ms2
                Dim prop As String = m2.Groups("prop").Value
                Dim val As String = m2.Groups("value").Value
                If prop.ToLower() <> "runat" Then
                    createCC += id + "." + prop + " = """ + val + """;" + vbCrLf
                End If
            Next

            'add the control to the control collection
            createCC += "this.Controls.Add(" + id + ");" + vbCrLf + vbCrLf
        End If

    Next

    'render the final html after the last control
    Dim htmlstr2 As String = theText.Substring(startindex, _
                                   theText.Length - startindex)
    htmlstr2.Replace("""", """""")
    renderCC += "writer.Write(@""" + htmlstr2 + """);" + vbCrLf
    'now show the text om the output window
    Dim win As Window = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindOutput)
    Dim OWp As OutputWindowPane = win.Object.OutputWindowPanes.Item(1)
    OWp.Clear()
    OWp.Activate()
    OWp.OutputString("-----------------" + vbCrLf)
    OWp.OutputString("Add this to the Init procedure" & _ 
                          " (before any events are assigned)" + vbCrLf)
    OWp.OutputString("TODO check type casing and property types," & _
                       " dynamically load templated elements" + vbCrLf)
    OWp.OutputString("-----------------" + vbCrLf)
    OWp.OutputString(createCC)
    OWp.OutputString("-----------------" + vbCrLf)
    OWp.OutputString("Add this to the render function" + vbCrLf)
    OWp.OutputString("-----------------" + vbCrLf)
    OWp.OutputString(renderCC)
    OWp.TextDocument.Selection.GotoLine(OWp.TextDocument.EndPoint().Line())
    DTE.ExecuteCommand("View.Output")
End Sub

Just copy paste the code into the .ascx.cs file and inherit from WebControl instead of UserControl. (Or if you want, create a new class file with both the code.)

Unfortunately, you'll have to check the casing of the types because if there is <asp:button in the ascx file, then the type will be button (lowercase), also check the type of the parameters assigned. (String type is assumed, see Button1.BorderWidth = "4px"; this should be just 4 of course.)

Well, good luck and hope this saves some typing.

Greetings Rooc.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here