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:
Then this macro will output the following lines to the output window:
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
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.