2010-02-01 76 views
9

Sau khi di chuyển các dự án Visual Studio 2003 sang VS2005 (hoặc VS2008), biểu mẫu của tôi vẫn nằm trong một tệp.Chuyển đổi Visual Studio 2003 biểu mẫu sang dạng Visual Studio 2005/2008 bằng cách sử dụng một phần lớp và tệp thiết kế

Các biểu mẫu mới trên VS2005 và VS2008 được tạo bằng cách sử dụng các lớp từng phần nơi tất cả mã được tạo bởi trình chỉnh sửa được lưu giữ trong tệp Designer.cs.

Vì hình thức VS2005 tạo ra là cách tốt hơn để xử lý biểu mẫu, tôi muốn biết liệu có cách chuyển đổi tất cả các biểu mẫu đơn cũ sang phương thức lớp VS2005 hay không.

Tôi đã thực hiện một số bằng tay nhưng điều này rất phức tạp và có thể dẫn đến một số lỗi nghiêm trọng.

Mọi đề xuất? Tái bút: Tôi đang sử dụng Microsoft Visual C# 2008 Express Ấn bản.

Trả lời

7

Điều này dường như là những gì bạn muốn.

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

NET 2.0 giới thiệu các lớp học phần cho phép “.designer” tập tin trong Visual Studio 2005 và sau đó. Tức là, tất cả các hình ảnh mã do nhà thiết kế tạo ra (các khai báo điều khiển, phương thức InitializeComponent , vv) có thể được giữ trong một tệp riêng biệt với mã thông thường của bạn. Khi bạn mở một .NET 1.x Visual Studio 2003 WinForms dự án trong Visual Studio 2005/2008 nó sẽ nâng cấp dự án của bạn lên .NET 2.0 chỉ tốt, nhưng tiếc là nó không di chuyển các lớp WinForms của bạn qua cấu trúc dự án “.designer” mới.

Ban đầu tôi nghĩ này sẽ là một công việc cho một DXCore plug-in (khuôn khổ miễn phí khi mà CodeRush được xây dựng) vì nó cung cấp plug-in với một mô hình đối tượng của mã mà có thể được sử dụng để lấy tất cả các thành viên phù hợp và di chuyển chúng vào một tệp thiết kế. Trước khi tôi nhìn vào điều này mặc dù tôi đã kiểm tra những gì các tùy chọn đã được đơn giản chỉ cần thực hiện nó như là một Visual Studio Macro. Tôi đã hoàn toàn mong đợi phải sử dụng một biểu thức chính quy để grep tệp mã để thực hiện tác vụ, nhưng thật ngạc nhiên để thấy rằng API mở rộng Visual Studio có sẵn cho các macro cung cấp một mô hình mã (dựa trên .NET. CodeDom tôi đoán) mà bạn có thể duyệt qua để kiểm tra và thao tác mã cơ bản. Vì vậy, đây là những gì kết quả “ExtractWinFormsDesignerFile” vĩ mô làm:

  • Định vị các lớp đầu tiên trong hạng mục công trình được lựa chọn (DTE.SelectedItems.Item (1) .ProjectItem) bằng cách đi qua các ProjectItem.FileCodeModel.CodeElements
  • chiết xuất InitializeComponent và Vứt bỏ các phương pháp từ lớp bằng CodeClass.Members đi qua
  • chiết xuất tất cả các lĩnh vực kiểm soát: có nghĩa là, tất cả các lĩnh vực có loại có nguồn gốc từ System.Windows.Forms.Control hoặc System.ComponentModel.Container hoặc có gõ tên bắt đầu bằng System.Windows.Forms
  • Đặt tất cả mã được trích xuất vào tệp “FormName.Designer.cs” mới.

này hiện là C# chỉ - nó có thể dễ dàng được chuyển đổi sang tạo ra mã VB.NET hoặc sử dụng phù hợp các FileCodeModel đúng và lẽ tạo mã trong một cách ngôn ngữ-agnostic khi tạo file thiết kế. Tôi lấy một phím tắt chỉ trong việc tạo ra các tập tin thiết kế như một chuỗi và viết nó trực tiếp vào một tập tin.

Để “cài đặt”: download the macro text:

' ------------------------------------------------------------------------- 
    ' 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 

và sao chép các phương pháp thành một Visual Studio Mô-đun Macro (sử dụng ALT + F11 để hiển thị các trình soạn Macro).
Cách sử dụng:

  • Chọn một mẫu Windows trong Solution Explorer
  • Run macro bằng cách hiển thị Explorer Macro (ALT + F8) và kích đúp vào ‘ExtractWinFormsDesignerFile’ vĩ mô. (Rõ ràng là bạn có thể móc macro lên nút thanh công cụ nếu bạn muốn.)
  • Sau đó bạn sẽ được nhắc thực hiện thủ công phần Lớp biểu mẫu (một bit khác tôi quá lười để tìm hiểu cách làm macro): tức là thay đổi lớp MyForm công cộng: Mẫu để partial class nào MyForm: Mẫu
+0

Tôi nghĩ rằng tôi sẽ không làm việc trên các ấn bản thể hiện. :-( – Jonas

+1

Bạn không thể tìm thấy một công cụ sẽ hoạt động nhanh, tuy nhiên, điều này hy vọng là một lần - bạn sẽ có thể tải xuống phiên bản beta hoặc eval để xử lý macro/plugin. –

2

Như bạn đã biết, tất cả các phiên bản Express không hỗ trợ phần mở rộng của bên thứ ba. Thật không may tôi biết không có công cụ đứng một mình có thể làm những gì bạn đang yêu cầu.

Tôi đã thử nghiệm chia tách lớp Winform thành các lớp partials. Khi bạn phát hiện ra, nó không phải là một công việc tầm thường. This câu hỏi đã được hỏi trước. Không giống như nỗ lực Martin's, tôi đi theo hướng khác. Thay vì tạo một tệp thiết kế, tôi đã đổi tên tệp hiện có thành MyForm.Designer.cs và tạo tệp MyForm.cs mới. Sau đó tôi tiến hành theo cách tương tự, di chuyển "mã phía sau" thay vì mã thiết kế vào lớp mới của tôi.

Điểm gắn bó với một trong các kỹ thuật này là các thay đổi trong tương lai đối với biểu mẫu vẫn không tạo ra trong tệp lớp chính xác. Điều này là do tệp dự án vẫn không nhận ra hai tệp được liên kết với nhau. Tùy chọn duy nhất của bạn là chỉnh sửa thủ công tệp dự án trong trình soạn thảo văn bản. Tìm kiếm như sau:

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

Thay <SubType>...</SubType> với <DependentUpon>MyForm.cs</DependentUpon> nên kết quả cuối cùng trông giống như:

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

Một giải pháp tôi đã thử nghiệm với chỉ đơn giản tạo ra một hình thức mới và kéo điều khiển từ hình thức cũ cho nó. Điều này thực sự làm việc đến một mức độ. Tất cả các điều khiển được di chuyển cùng với tất cả các thuộc tính của chúng. Những gì không di chuyển là trình xử lý sự kiện. Bạn sẽ phải cắt và dán từ biểu mẫu cũ, sau đó đi qua từng điều khiển và chọn lại trình xử lý thích hợp từ trình thiết kế biểu mẫu. Tùy thuộc vào độ phức tạp của biểu mẫu, đây có thể là giải pháp thay thế hợp lý.

Từ kinh nghiệm cá nhân của riêng tôi hỗ trợ nhiều giao diện người dùng, cách tiếp cận tốt nhất là giữ thiết kế biểu mẫu đơn giản và tách logic nghiệp vụ khỏi giao diện người dùng hoàn toàn. Các MVP Passive view hoạt động khá tốt cho việc này. Bằng cách ủy thác phần lớn trách nhiệm cho một lớp người trình bày, nó trở nên tầm thường để thực hiện biểu mẫu trong một khung công tác UI khác nhau. WinForms, WebForms, WPF, vv, nó tạo ra sự khác biệt nhỏ cho lớp trình bày. Tất cả những gì nó thấy trong một giao diện hiển thị một danh sách các thuộc tính mà nó thao tác. Tất nhiên tất cả những người khờ dại khờ khạo trên thế giới sẽ không giúp được gì khi vấn đề bạn đang đối mặt ở đây và bây giờ.

Các vấn đề liên quan