{"id":44473,"date":"2023-02-23T10:15:00","date_gmt":"2023-02-23T18:15:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/dotnet\/?p=44473"},"modified":"2023-02-27T10:22:54","modified_gmt":"2023-02-27T18:22:54","slug":"winforms-codegen-update","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/winforms-codegen-update\/","title":{"rendered":"Updated Modern Code Generation for WinForm&#8217;s InitializeComponent"},"content":{"rendered":"<p>When you create a WinForms Form or User Control with the WinForms Designer in\nVisual Studio, it does not have a special definition or file format like XML or\nHTML to represent the user interface. From the beginning, the only format\nWinForms has used is program code. A Form or User Control defined in a WinForms\nVisual Basic project gets saved into VB Code. In a C# project, that is C# code.\nThat code will be placed in a dedicated Designer file, which sits behind the\nactual Form code file and contains the code to control the UI.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2023\/02\/CodeBehindFile.png\" alt=\"Screenshot of a WinForms Form code-behind Designer file in the Solution Explorer\" \/><\/p>\n<p>When your Form or User Control needs to be opened again inside of the WinForms\nDesigner, that code is interpreted and &#8211; based on the resulting object graph &#8211;\nthe Form\/User Control gets recreated in the Designer. That is the reason we call\nthe process of saving a Form <em>CodeDOM serialization<\/em>.\n<a href=\"https:\/\/learn.microsoft.com\/dotnet\/framework\/reflection-and-codedom\/using-the-codedom\">CodeDOM<\/a>\nhere refers to an object model (the <em>Code <strong>D<\/strong>ocument <strong>O<\/strong>bject <strong>M<\/strong>odel<\/em>)\nwhich allows the developer to define aspects of a program or part of a program\nby objects of certain types.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2023\/02\/ButtonToCode.png\" alt=\"Screenshot of a WinForms Form with a Button and the respective generated code in InitializeComponent\" \/><\/p>\n<p>While CodeDOM is pretty flexible, can be extended comparatively easily and\nsupports more languages than Visual Basic or C#, generating a CodeDOM graph from\nan existing code file is a completely different beast. And although CodeDOM\n<em>has<\/em> the option to actually write a code file for particular languages through\nits existing <a href=\"https:\/\/learn.microsoft.com\/dotnet\/framework\/reflection-and-codedom\/generating-and-compiling-source-code-from-a-codedom-graph\">Compiler\nimplementation<\/a>,\nthe style of that resulting code is the same it has been from the beginning of\n.NET Framework, which is in many cases no longer up to current coding standards.<\/p>\n<p>In WinForms, when you design a Form, everything which is relevant is generated\nin one method per Form or User Control. That method (amongst a bit of\ninfrastructure and initialization code in addition) is called\n<code>InitializeComponent<\/code>.<\/p>\n<p>This method is called by a Form&#8217;s constructor unconditionally. In the C# case\nthat&#8217;s pretty obvious, where a new Form which you add to your project, always\nhas that constructor and the required call:<\/p>\n<pre><code class=\"language-csharp\">    public partial class Form1 : Form\r\n    {\r\n        public Form2()\r\n        {\r\n            InitializeComponent();\r\n        }\r\n    }<\/code><\/pre>\n<p>In Visual Basic, if you don&#8217;t add a constructor <code>Sub New<\/code> explicitly, the Visual\nBasic compiler inserts the call to <code>InitializeComponent<\/code> automatically in the\nbackground. If you however add a constructor to the code file, the editor also\ninserts the call to <code>InitializeComponent<\/code> in the VB code:<\/p>\n<pre><code class=\"language-vb\">Public Class Form1\r\n\r\n    Sub New()\r\n\r\n        ' This call is required by the designer.\r\n        InitializeComponent()\r\n\r\n        ' Add any initialization after the InitializeComponent() call.\r\n\r\n    End Sub\r\nEnd Class<\/code><\/pre>\n<blockquote>\n<p>Note that in Visual Basic, the <code>Inherits<\/code> statement, which lets your new Form\nclass inherit from the <code>System.Windows.Forms.Form<\/code> base class, in contrast to C#\nis only part of the Designer code behind file. In VB it&#8217;s also sufficient for a\npartial class only to state the <a href=\"https:\/\/learn.microsoft.com\/dotnet\/visual-basic\/language-reference\/modifiers\/partial\"><code>Partial<\/code>\nkeyword<\/a>\nin one of the partial class&#8217; code files. That is the reason why a Visual Basic\nWinForms Form code file does not contain anything but the Form&#8217;s class\ndefinition by default.<\/p>\n<\/blockquote>\n<p>Up to recently, the WinForms Designer used the <a href=\"https:\/\/learn.microsoft.com\/dotnet\/api\/envdte.codemodel?view=visualstudiosdk-2022\">CodeModel\nInterface<\/a>\nto interpret source code of the different programming language to build the\nrequired internal CodeDOM graph for the Designer to hold a Form&#8217;s or a User\nControl&#8217;s definition. But we changed that.<\/p>\n<h2>Enter Roslyn<\/h2>\n<p>WinForms introduced with Visual Studio 2022 version 17.5 a modernized way to\nread and generate the code for <code>InitializeComponent<\/code> for the <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/state-of-the-windows-forms-designer-for-net-applications\/\">WinForms\nOut-of-Process\nDesigner<\/a>.\nIt does so by using the APIs of the <a href=\"https:\/\/learn.microsoft.com\/dotnet\/csharp\/roslyn-sdk\/\">.NET Compiler\nPlatform<\/a> &#8211; better know\nas the Roslyn SDK &#8211; for all related tasks. The Roslyn Compiler is a set of\nopen-source compilers and code analysis APIs for .NET languages. It allows\ndevelopers to write, analyze, and manipulate code in C# and Visual Basic .NET\nusing modern language features. It also provides a rich set of diagnostic and\ncode refactorings to improve code quality and developer productivity. It is the\ngold standard and the current best practice for code generation in C# and VB.\nAnd, since it&#8217;s the same tooling that is used for compilation and build purposes\ninside Visual Studio for any C# or Visual Basic project its code generation\nresult is completely in-line with current coding standards.<\/p>\n<p>Also, since the Roslyn compiler provides certain APIs to not know only about the\ncorrect <a href=\"https:\/\/learn.microsoft.com\/dotnet\/csharp\/roslyn-sdk\/work-with-syntax?source=recommendations\">syntax of a particular statement, command or method<\/a>, but also about <a href=\"https:\/\/learn.microsoft.com\/dotnet\/csharp\/roslyn-sdk\/work-with-semantics\">the\nsemantics of a code block<\/a> already at WinForms design time, the WinForms designer\ncan point out potential problems with the code inside of <code>InitializeComponent<\/code>\nfar earlier and more precisely than before. So, it not only knows when you&#8217;ve\nspelled &#8216;Buttne&#8217; wrong &#8211; it would also know that a variable with a typo defined\ninside of <code>InitializeComponent<\/code> would be an unknown symbol, and be able to point\nthat out.<\/p>\n<p>But there is a series of additional benefits:<\/p>\n<ul>\n<li>Previously, the CodeModel based building up of the CodeDOM could only run on\nthe UI Thread. That was not only a blocking operation, it couldn&#8217;t utilize the\nfull potential of a modern, multi-core processor.  Using the Roslyn compiler,\nwe will be able to optimize the building process over time by using\nparallelization.<\/li>\n<li>The old system didn&#8217;t have an easy way to interpret more recently introduced\nlanguage features. Using Roslyn, we will have the option to introduce language\nfeatures like <code>NameOf<\/code> to generate more robust code, especially for data\nbinding purposes. In addition it opens up the path to more complex code\ngeneration inside of <code>InitializeComponent<\/code> in the future, which will help to\noptimize and equalize code generation for HighDPI scenarios generated on\nmachines with different HighDPI settings.<\/li>\n<li>The Roslyn compiler honors many aspects of <a href=\"https:\/\/learn.microsoft.com\/visualstudio\/ide\/create-portable-custom-editor-options?view=vs-2022\">.editorconfig\nconfigurations<\/a>,\nso the code generated in <code>InitializeComponent<\/code> is close to what you and your\nteam are enforcing as your coding standards by custom .editorconfig\ndefinitions.<\/li>\n<\/ul>\n<p>That all said, there are a couple of coding elements which are fundamentally\ndifferent than before. The omission of <code>this<\/code> in C# or <code>Me<\/code> in Visual Basic is\none of such an example. The following screenshot shows the difference in the\ncode generation with Roslyn for a Button in <code>InitializeComponent<\/code>:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2023\/02\/CodeGenDiff.png\" alt=\"Screenshot of a diff of InitializeComponent with the classic and the new Roslyn-based code generation\" \/><\/p>\n<p>If you&#8217;re interested in a more technical background about moving the code\ngeneration in the WinForms designer to Roslyn or how to configure the\n<code>InitializeComponent<\/code> code generation with .editorconfig, <a href=\"https:\/\/github.com\/dotnet\/winforms\/blob\/main\/docs\/designer\/modernization-of-code-behind-in-OOP-designer\/modernization-of-code-behind-in-oop-designer.md\">take a look at this\ntechnical article in the WinForms\nrepo<\/a>\nwho points out all those things in greater detail.<\/p>\n<p>Feedback about the subject matter is really important to us, so please let us\nknow your thoughts or ideas you might have around WinForms code generations in\nthe comments. If you have suggestions around the WinForms Designer or think you\nfound a bug, feel free to file new issues in the <a href=\"https:\/\/github.com\/dotnet\/winforms\">WinForms Github\nrepo<\/a>.<\/p>\n<p>Happy designing and coding!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When you design a WinForms Form, it gets generated into a method called InitializeComponent. When you reopen that Form, it gets recreated by interpreting that code. In Visual Studio 2022 17.5, we&#8217;ve modernized the code generation process. And made some changes.<\/p>\n","protected":false},"author":9483,"featured_media":44474,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685,756,7199,7163],"tags":[],"class_list":["post-44473","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-csharp","category-visual-basic","category-winforms"],"acf":[],"blog_post_summary":"<p>When you design a WinForms Form, it gets generated into a method called InitializeComponent. When you reopen that Form, it gets recreated by interpreting that code. In Visual Studio 2022 17.5, we&#8217;ve modernized the code generation process. And made some changes.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/44473","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/9483"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=44473"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/44473\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/44474"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=44473"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=44473"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=44473"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}