Converting Visual Studio 2003 WinForms to Visual Studio 2005/2008 partial classes

.NET 2.0 introduced partial classes which enables “.designer” files in Visual Studio 2005 and later. That is, all of the visual designer-generated code (control declarations, the InitializeComponent method, etc) can be kept in a file separate from your regular code. When you open up a .NET 1.x Visual Studio 2003 WinForms project up in Visual Studio 2005/2008 it will upgrade your project to .NET 2.0 just fine, but unfortunately it doesn’t migrate your WinForms classes over to the new “.designer” project structure.

Initially I thought this would be a job for a DXCore plug-in (the free framework upon which CodeRush is built) as it provides plug-ins with an object model of the code which could be used to grab all the right members and move them over into a designer file. Before I looked into this though I checked what the options were for simply implementing it as a Visual Studio Macro. I was fully expecting to have to use a regular expression to grep the code file to perform the task, but was pleasantly surprised to find that the Visual Studio extensibility API in available to macros provides a code model (based on the .NET CodeDom I presume) which you can traverse to inspect and manipulate the underlying code.

So, here’s what the resulting “ExtractWinFormsDesignerFile” macro does:

  • Locates the first class in the selected project item (DTE.SelectedItems.Item(1).ProjectItem) by traversing the ProjectItem.FileCodeModel.CodeElements
  • Extracts the InitializeComponent and Dispose methods from the class by traversing CodeClass.Members
  • Extracts all control fields: that is, all fields whose type derives from System.Windows.Forms.Control or System.ComponentModel.Container or whose type name starts with System.Windows.Forms
  • Puts all the extracted code into  a new “FormName.Designer.cs” file.

This is currently C# only – it could easily be converted to generated VB.NET code or adapted use the FileCodeModel properly and perhaps create the code in an language-agnostic way when generating the designer file. I took a shortcut in just generating the designer file as a string and writing it directly to a file.

To “install”: download the macro text and copy the methods into a Visual Studio Macro Module (use ALT+F11 to show the Macro editor).

To use:

  • Select a Windows Form in the Solution Explorer
  • Run the macro by showing the Macro Explorer (ALT+F8) and double-clicking the ‘ExtractWinFormsDesignerFile’ macro. (Obviously you can hook the macro up to a toolbar button if you like.)
  • You will then be prompted to manually make the Form class partial (another bit I was too lazy to work out how to get the macro to do): i.e. change
    public class MyForm : Form
    to
    public partial class MyForm : Form

Please leave a comment if this helps you.

14 comments so far

  1. Mike Smith on

    Hi Duncan
    I came across your blog today and have just converted a project with over 100 forms to partial classes using your macro.
    Thanks a lot for saving me a lot of work.

    Mike Smith

  2. Jaggy on

    Big thanks. Works like a charm.

  3. Jose A. Ramirez on

    I run the macro and it creates the designer class but the form in designer mode shows no controls just a blank grey form..

    Please let me know if I am missing something.

    Thanks,
    Jose A. Ramirez

  4. Duncan Smart on

    @Jose: yes I think you are missing something. Namely the last point: “manually make the Form class partial”.

  5. Jose A. Ramirez on

    Hi Duncan,
    it works perfectly now!
    Thanks much,
    Jose

  6. Alper on

    Hi Duncan,

    Download link seems to be broken. Could you email macro code to me?

    Thanks,
    Alper

  7. Diana on

    Great work! Save my life!

  8. lakshmipathy on

    Thank you. you save a lot of time. i want to generate a boiler plate template so i used your code for getting the namespace and class name. thank you

  9. Max on

    Thanks a lot!
    Very useful tool!

  10. Adam Best on

    Hey man,

    Awesome macro, really helped me out a lot!

    I made a few enhancements, like only creating the designer if one doesn’t exist already, and automatically making the original class partial…

    Sub ExtractWinFormsDesignerFile()


    Dim newItemPath As String = dir & “\” & bareName & “.Designer.cs”

    ‘Check if designer file already exists
    ‘If it does, don’t create one — Adam Best
    Dim childItems As ProjectItems = item.ProjectItems
    Dim childItem As ProjectItem
    Dim designer As Boolean = False

    For Each childItem In childItems
    If (childItem.FileNames(1) = newItemPath) Then
    designer = True
    Exit For
    End If
    Next

    If (Not designer) Then
    Dim codeClass As CodeClass = findClass(item.FileCodeModel.CodeElements)


    makeOriginalClassPartial(item.FileCodeModel.CodeElements)

    End If
    End Sub

    And the added function is…

    ‘Make original class partial — Adam Best
    Function makeOriginalClassPartial(ByVal items As System.Collections.IEnumerable)

    Dim text As String = String.Empty
    Dim newText As String = String.Empty

    For Each codeEl As CodeElement In items
    If codeEl.Kind = vsCMElement.vsCMElementClass Then
    Dim start As EditPoint = codeEl.GetStartPoint().CreateEditPoint()
    Dim endPoint As TextPoint = codeEl.GetStartPoint(vsCMPart.vsCMPartBody)
    text = start.GetText(endPoint)
    If (Not text.Contains(“partial class”)) Then
    newText = text.Replace(“class”, “partial class”)
    start.Delete(endPoint)
    start.Insert(newText)
    End If
    ElseIf codeEl.Children.Count > 0 Then
    Dim partialOrigClass As Boolean = makeOriginalClassPartial(codeEl.Children)
    End If
    Next

    End Function

    • Duncan Smart on

      Thanks Adam, I’ll look into updating my code with your changes.

  11. Guy on

    Very nice. I don’t know why VS doesn’t do this automatically to clean things up!

    Thank you!

  12. David C on

    Thank you so much! Not only does it work for windows forms, but also third party tools such as Datadynamics’ Active Reports.

  13. Harald Mühlhoff on

    Thanks a lot! Worked as “advertised” … ;)


Leave a reply