在.NET Core 3.0 Preview上使用Windows窗體設計器


支持使用基於Windows窗體應用程序的.NET Core 3.0(預覽)的Windows窗體設計器

 

介紹

截至撰寫本文時,Microsoft和社區目前正在測試.NET Core 3.0如果您在.NET Core 3.0的一般可用性之后閱讀本文,請跳過本文。否則,繼續。

Windows Forms一直是維護企業/企業桌面應用程序的巔峰之作。盡管有着開發桌面應用程序的古老機制,但微軟能夠認識到經過實戰測試的工具包的優勢,並決定將其轉移到現代.NET Core平台(以前稱為.NET Framework)。

到目前為止,他們設法通過Windows窗體轉換很好地將事物整合在一起,但是缺少早期采用者的一些關鍵組件,其中一個恰好是Windows窗體設計器; Microsoft Visual Studio內置的工具,旨在簡化用戶界面開發。要確認.NET Core 3.0預覽中的Windows窗體設計器限制,請嘗試打開並設計任何表單/用戶控制文件(通常是新創建的項目中的Form1.cs。)因此,文章的結果存在。本文將指導您如何克服.NET Core 3.0預覽版Windows窗體設計器的限制,而無需等待其一般可用性。

 

軟件要求

要繼續閱讀本文,您必須在系統上安裝以下組件:

  1. Microsoft Visual Studio 2019 - 至少版本16.2.0
  2. .NET Core 3.0預覽版7(截至編寫本文時,將使用預覽版7)

克服限制

證明問題

  1. 創建一個新的Windows窗體應用程序(.NET Core)。如果您看不到左側的條目,請使用方便的“ 搜索模板”搜索框並鍵入“ Windows Forms App(.NET Core) ”。

    圖1用於在.NET Core 3.0預覽版上使用Windows窗體設計器

  2. 對於這個項目,我們將命名它DotNetCore.WinForms,但你可以任意命名,確保理解這個概念,你會很高興。
  3. 如果沒有進行任何更改,請嘗試打開Form1.cs 文件,您應該看到類似的內容。請不要驚慌,這是正常行為,因為我們正在運行.NET Core 3.0的預覽版本。我們稍后會解決這個問題。

    圖2用於在.NET Core 3.0預覽版上使用Windows窗體設計器

此時,您開始感覺到在.NET Core 3.0預覽下無法進行任何類型的用戶界面設計。

解決方案

為了解決這個限制,我們可以使用一種方法,通過基於功能齊全的.NET Framework創建一個額外的Windows Forms項目,我們可以間接地利用.NET Core項目的設計。請繼續直到最后。

  1. 右鍵單擊解決方案名稱,然后創建一個名為_TemporaryFixup的新解決方案文件夾

    圖3用於在.NET Core 3.0預覽版上使用Windows窗體設計器

  2. _TemporaryFixup解決方案文件夾下,創建一個新的Windows窗體應用程序(.NET Framework)項目。如果您看不到左側的條目,請使用方便的“ 搜索模板 ”搜索框並鍵入“ Windows Forms App(.NET Framework) ”。

    圖4用於在.NET Core 3.0預覽版上使用Windows窗體設計器

  3. 對於這個項目,我們將命名為DotNetFramework.WinForms,但您可以將其命名為任何您喜歡的名稱。
  4. 刪除Form1.cs 文件。
  5. 右鍵單擊該DotNetFramework.WinForms項目,然后單擊“ 屬性”
  6. 將默認命名空間更改為與.NET Core項目相同; 在我們的例子中,我們將其設置為DotNetCore.WinForms(將在幾個中解釋)
  7. 創建一個新表單並將其命名為您喜歡的任何名稱。

現在,讓我們使用以下命令修改項目中的Program.cs文件DotNetFramework.WinForms

 

 1 using System;
 2 using System.IO;
 3 using System.Linq;
 4 
 5 namespace DotNetFramework.WinForms
 6 {
 7     static class Program
 8     {
 9         private static string SourceProjectDir = 
10             @"C:\Users\ahmad\source\repos\DotNetCore.WinForms\DotNetFramework.WinForms";
11         private static string TargetProjectDir = 
12             @"C:\Users\ahmad\source\repos\DotNetCore.WinForms\DotNetCore.WinForms";
13 
14         [STAThread]
15         static void Main()
16         {
17             var directory = new DirectoryInfo(SourceProjectDir);
18 
19             var srcFiles = directory.GetFiles("*.Designer.cs", SearchOption.AllDirectories);
20 
21             foreach (var srcFile in srcFiles)
22             {
23                 // Get the relative directory
24                 var relativeDirectory = $"{srcFile.DirectoryName.Substring
25                                 (SourceProjectDir.Length, 
26                                 srcFile.DirectoryName.Length - SourceProjectDir.Length)}";
27 
28                 // Append the determined relative directory to the corresponding designer 
29                 // & C# source files related to the form.
30                 var designerFileName = $@"{relativeDirectory}\{srcFile.Name}";
31                 var noDesignerFileName = 
32                   $@"{relativeDirectory}\{srcFile.Name.Replace(".Designer", "")}";
33 
34                 var srcDesignerFile = $"{SourceProjectDir}{designerFileName}";
35                 var srcNoDesignerFile = $"{SourceProjectDir}{noDesignerFileName}";
36 
37                 var dstDesignerFile = $"{TargetProjectDir}{designerFileName}";
38                 var dstNoDesignerFile = $"{TargetProjectDir}{noDesignerFileName}";
39 
40                 // Create an array based on the relative location.
41                 var dirs = relativeDirectory.Split('\\').ToList();
42 
43                 // Keep track of where were we when we created a directory.
44                 var currentDir = TargetProjectDir;
45 
46                 // Start creating the missing directories in our target project.
47                 foreach (var dir in dirs)
48                 {
49                     currentDir = Path.Combine(currentDir, dir);
50                     Directory.CreateDirectory(currentDir);
51                 }
52 
53                 // Overwrite the file to the targeted project.
54                 File.Copy(srcDesignerFile, dstDesignerFile, true);
55 
56                 // If our UI logic is unavailable, that means we've created 
57                 // a new form from the source project.
58                 // so we copy the form's UI logic code to the target project.
59                 if (!File.Exists(dstNoDesignerFile) && File.Exists(srcNoDesignerFile))
60                 {
61                     File.Copy(srcNoDesignerFile, dstNoDesignerFile, false);
62                 }
63             }
64         }
65     }
66 }

由於我們專注於在.NET Core平台上開發我們的應用程序,因此我們不需要顯示.NET Framework對應的任何對話框。我們寧願*只將.NET Framework項目的用戶界面設計部分反映到.NET Core項目中。這幾乎可以解釋為什么我們之前將默認命名空間更改為.NET Framework項目,還記得嗎?

確保修改SourceProjectDir變量以保存.NET Framework項目目錄,並使用TargetProjectDir變量保存.NET Core項目目錄。

接下來,我們想要在每次構建和運行.NET Core項目時調出.NET Framework可執行文件。在我們繼續前進之前,首先構建整個解決方案。其次,右鍵單擊.NET Framework項目並單擊Properties,然后從左側的選項卡中選擇Build Events在“ 預構建事件命令行 ”字段中,粘貼以下內容:

 

1 $(TargetPath)

最后,您可以從.NET Framework項目開始設計用戶界面元素,並通過按Ctrl + Shift + B自動反映您對.NET Core項目的更改,然后運行!

使用代碼

上面提供的代碼本質上是一個反射器。它僅反映.NET Framework項目的.NET Framework項目的表單文件。您可以無限制地修改代碼,使其按照您的意圖執行操作。

興趣點

Windows窗體設計器的便利性已被帶回。無論您是計划在.NET Core下使用Windows Forms重新開始,還是遷移現有的基於.NET Framework的傳統項目,您現在都可以輕松地繼續這樣做,而無需等待.NET Core 3.0的一般可用性。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM