繁体   English   中英

使用部分类和Designer文件将Visual Studio 2003表单转换为Visual Studio 2005/2008表单

[英]Convert Visual Studio 2003 forms to Visual Studio 2005/2008 forms using partial classes and Designer files

将我的Visual Studio 2003项目迁移到VS2005(或VS2008)后,我的表单仍然在单个文件中。

VS2005和VS2008上的新表单是使用部分类创建的,其中编辑器生成的所有代码都保存在Designer.cs文件中。

由于VS2005表单创建是一种更好的处理表单的方法,我想知道是否有一种方法可以将所有旧的单文件格式转换为VS2005分类方法。

我已经完成了一些手工操作,但这非常棘手,可能导致一些严重的错误。

有什么建议? PS:我正在使用Microsoft Visual C#2008 Express Edition。

这似乎是你想要的。

将Visual Studio 2003 WinForms转换为Visual Studio 2005/2008部分类

NET 2.0引入了部分类,它在Visual Studio 2005及更高版本中启用“.designer”文件。 也就是说,所有可视化设计器生成的代码(控件声明,InitializeComponent方法等)都可以保存在与常规代码分开的文件中。 当您在Visual Studio 2005/2008中打开.NET 1.x Visual Studio 2003 WinForms项目时,它会将您的项目升级到.NET 2.0,但不幸的是它不会将您的WinForms类迁移到新的“。设计师“项目结构。

最初我认为这将是DXCore插件(构建CodeRush的免费框架)的工作,因为它为插件提供了代码的对象模型,可用于获取所有正确的成员并移动它们进入设计师档案。 在我调查之前,我检查了将它作为Visual Studio宏实现的选项。 我完全期望必须使用正则表达式来grep代码文件来执行任务,但是惊喜地发现可用于宏的Visual Studio可扩展性API提供了代码模型(基于.NET CodeDom我假设) )您可以遍历以检查和操作底层代码。 那么,这就是生成的“ExtractWinFormsDesignerFile”宏的作用:

  • 通过遍历ProjectItem.FileCodeModel.CodeElements找到所选项目项(DTE.SelectedItems.Item(1).ProjectItem)中的第一个类
  • 通过遍历CodeClass.Members从类中提取InitializeComponent和Dispose方法
  • 提取所有控制字段:即,类型派生自System.Windows.Forms.Control或System.ComponentModel.Container或其类型名称以System.Windows.Forms开头的所有字段
  • 将所有提取的代码放入新的“FormName.Designer.cs”文件中。

这只是目前的C# - 它可以很容易地转换为生成的VB.NET代码或者适当地使用FileCodeModel,并且可能在生成设计器文件时以与语言无关的方式创建代码。 我采用了一种快捷方式,只是将设计器文件生成为字符串并将其直接写入文件。

要“安装”: 下载宏文本

    ' -------------------------------------------------------------------------
    ' Extract WinForms Designer File Visual Studio 2005/2008 Macro
    ' -------------------------------------------------------------------------
    ' Extracts the InitializeComponent() and Dispose() methods and control
    ' field delarations from a .NET 1.x VS 2003 project into a VS 2005/8 
    ' style .NET 2.0 partial class in a *.Designer.cs file. (Currently C# 
    ' only)
    ' 
    ' To use: 
    '  * Copy the methods below into a Visual Studio Macro Module (use 
    '    ALT+F11 to show the Macro editor)
    '  * Select a Windows Form in the Solution Explorer
    '  * Run the macro by showing the Macro Explorer (ALT+F8) and double
    '    clicking the 'ExtractWinFormsDesignerFile' macro.
    '  * You will then be prompted to manually make the Form class partial: 
    '    i.e. change "public class MyForm : Form"
    '          to
    '             "public partial class MyForm : Form"
    '
    ' Duncan Smart, InfoBasis, 2007
    ' -------------------------------------------------------------------------

    Sub ExtractWinFormsDesignerFile()
        Dim item As ProjectItem = DTE.SelectedItems.Item(1).ProjectItem
        Dim fileName As String = item.FileNames(1)
        Dim dir As String = System.IO.Path.GetDirectoryName(fileName)
        Dim bareName As String = System.IO.Path.GetFileNameWithoutExtension(fileName)
        Dim newItemPath As String = dir & "\" & bareName & ".Designer.cs"

        Dim codeClass As CodeClass = findClass(item.FileCodeModel.CodeElements)
        Dim namespaceName As String = codeClass.Namespace.FullName

        On Error Resume Next ' Forgive me :-)
        Dim initComponentText As String = extractMember(codeClass.Members.Item("InitializeComponent"))
        Dim disposeText As String = extractMember(codeClass.Members.Item("Dispose"))
        Dim fieldDecls As String = extractWinFormsFields(codeClass)
        On Error GoTo 0

        System.IO.File.WriteAllText(newItemPath, "" _
          & "using System;" & vbCrLf _
          & "using System.Windows.Forms;" & vbCrLf _
          & "using System.Drawing;" & vbCrLf _
          & "using System.ComponentModel;" & vbCrLf _
          & "using System.Collections;" & vbCrLf _
          & "" & vbCrLf _
          & "namespace " & namespaceName & vbCrLf _
          & "{" & vbCrLf _
          & "   public partial class " & codeClass.Name & vbCrLf _
          & "   {" & vbCrLf _
          & "       #region Windows Form Designer generated code" & vbCrLf _
          & "       " & fieldDecls & vbCrLf _
          & "       " & initComponentText & vbCrLf _
          & "       #endregion" & vbCrLf & vbCrLf _
          & "       " & disposeText & vbCrLf _
          & "   }" & vbCrLf _
          & "}" & vbCrLf _
          )
        Dim newProjItem As ProjectItem = item.ProjectItems.AddFromFile(newItemPath)
        On Error Resume Next
        newProjItem.Open()
        DTE.ExecuteCommand("Edit.FormatDocument")
        On Error GoTo 0

        MsgBox("TODO: change your class from:" + vbCrLf + _
               "  ""public class " + codeClass.FullName + " : Form""" + vbCrLf + _
               "to:" + _
               "  ""public partial class " + codeClass.FullName + " : Form""")
    End Sub

    Function findClass(ByVal items As System.Collections.IEnumerable) As CodeClass
        For Each codeEl As CodeElement In items
            If codeEl.Kind = vsCMElement.vsCMElementClass Then
                Return codeEl
            ElseIf codeEl.Children.Count > 0 Then
                Dim cls As CodeClass = findClass(codeEl.Children)
                If cls IsNot Nothing Then
                    Return findClass(codeEl.Children)
                End If
            End If
        Next
        Return Nothing
    End Function

    Function extractWinFormsFields(ByVal codeClass As CodeClass) As String

        Dim fieldsCode As New System.Text.StringBuilder

        For Each member As CodeElement In codeClass.Members
            If member.Kind = vsCMElement.vsCMElementVariable Then
                Dim field As CodeVariable = member
                If field.Type.TypeKind <> vsCMTypeRef.vsCMTypeRefArray Then
                    Dim fieldType As CodeType = field.Type.CodeType
                    Dim isControl As Boolean = fieldType.Namespace.FullName.StartsWith("System.Windows.Forms") _
                       OrElse fieldType.IsDerivedFrom("System.Windows.Forms.Control") _
                       OrElse fieldType.IsDerivedFrom("System.ComponentModel.Container")
                    If isControl Then
                        fieldsCode.AppendLine(extractMember(field))
                    End If
                End If
            End If
        Next
        Return fieldsCode.ToString()
    End Function

    Function extractMember(ByVal memberElement As CodeElement) As String
        Dim memberStart As EditPoint = memberElement.GetStartPoint().CreateEditPoint()
        Dim memberText As String = String.Empty
        memberText += memberStart.GetText(memberElement.GetEndPoint())
        memberStart.Delete(memberElement.GetEndPoint())
        Return memberText
    End Function

并将方法复制到Visual Studio宏模块(使用ALT + F11显示宏编辑器)。
使用:

  • 在解决方案资源管理器中选择Windows窗体
  • 通过显示宏资源管理器(ALT + F8)并双击“ExtractWinFormsDesignerFile”宏来运行宏。 (显然,如果您愿意,可以将宏挂钩到工具栏按钮。)
  • 然后会提示您手动使Form类部分(另一点我懒得弄清楚如何让宏做):即将公共类MyForm:Form更改为public partial class MyForm:Form

您可能知道,所有Express版本都不支持第三方扩展。 不幸的是,我知道没有独立的工具可以做你想要的。

我已经尝试将Winform类拆分为partials类。 正如您所发现的那样,这不是一项微不足道的事情。 之前已经问过这个问题。 马丁的尝试不同,我走向另一个方向。 我没有创建设计器文件,而是将现有文件重命名为MyForm.Designer.cs并创建了一个新的MyForm.cs文件。 然后我以类似的方式进行,将“代码隐藏”而不是设计器代码移动到我的新类中。

使用这些技术中的任何一个的一个难点是未来对表单的更改仍然不会在正确的类文件中生成。 这是因为项目文件仍然无法识别要链接在一起的两个文件。 您唯一的选择是在文本编辑器中手动编辑项目文件。 寻找以下内容:

<Compile Include="MyForm.Designer.cs">
  <SubType>Form</SubType>
</Compile>

<SubType>...</SubType>替换为<DependentUpon>MyForm.cs</DependentUpon>以便最终结果如下所示:

<Compile Include="MyForm.Designer.cs">
  <DependentUpon>MyForm.cs</DependentUpon>
</Compile>

我尝试的另一个解决方案是简单地创建一个新表单并将控件从旧表单拖动到它。 这实际上在一定程度上起作用。 所有控件及其所有属性都已迁移。 没有迁移的是事件处理程序。 这些你必须从旧表单剪切和粘贴,然后遍历每个控件并从表单设计器重新选择适当的处理程序。 根据表单的复杂程度,这可能是一个合理的选择。

根据我自己支持多个UI的个人经验,最好的方法是保持表单设计简单,并将业务逻辑与UI完全分开。 MVP被动视图对此非常有效。 通过将尽可能多的责任委托给演示者类,在不同的UI框架中实现表单变得微不足道。 WinForms,WebForms,WPF等,它对演示者类没什么区别。 它在界面中看到它暴露了它操作的属性列表。 当然,当你面临的问题在这里和现在时,世界上所有的应有的意志都无济于事。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM