Browse Source
Description of modernization in winforms code-behind generation in the VS 2022 17.5 Preview3 (#8503)
Description of modernization in winforms code-behind generation in the VS 2022 17.5 Preview3 (#8503)
* Description of visible changes in winforms code-behind generationpull/8526/head

committed by
GitHub

No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 209 additions and 4 deletions
-
BINdocs/designer/modernization-of-code-behind-in-OOP-designer/images/Form1-Designer-C#-comparison.png
-
BINdocs/designer/modernization-of-code-behind-in-OOP-designer/images/Form1-Designer-VB-comparison.png
-
199docs/designer/modernization-of-code-behind-in-OOP-designer/modernization-of-code-behind-in-oop-designer.md
-
14docs/designer/readme.md
After Width: 2113 | Height: 1018 | Size: 241 KiB |
After Width: 2121 | Height: 963 | Size: 372 KiB |
@ -0,0 +1,199 @@ |
|||
# Modernization of code-behind in WinForms OOP designer |
|||
|
|||
## Background |
|||
|
|||
The WinForms designer saves visual representations of user controls or forms on the design surface to code-behind file (`Form1.Designer.cs` or `Form1.Designer.vb`). Control instances that developer sees on the design surface are represented as a CodeDOM tree (see [Using the CodeDOM](https://learn.microsoft.com/dotnet/framework/reflection-and-codedom/using-the-codedom)), that tree is saved to the generated code-behind file in the `InitializeComponent` method. We call this feature design time serialization. |
|||
|
|||
Previously COM-based [CodeModel interface](https://learn.microsoft.com/dotnet/api/envdte.codemodel?view=visualstudiosdk-2022) was used to write code into the editor's buffer as well as to generate CodeDOM tree from the source code when designer was loading. This COM object was accessible from the main thread only, which prevented parallelization in source code processing. Also, being more than 20 years old, it did not support some of the newer language features, for example the `nameof()` expression. |
|||
|
|||
## What's different |
|||
|
|||
Starting with [Visual Studio 2022 v17.5 Preview 3](https://visualstudio.microsoft.com/vs/preview/), the WinForms out-of-process designer uses [Roslyn](https://github.com/dotnet/roslyn) for design time serialization. |
|||
|
|||
In Preview 3, designer serializes more modern code into `InitializeComponent`. We have worked hard to ensure that you can take projects between this version of Visual Studio and earlier versions. Someday in the future, we may build on the improvements in our serialization to enable performance enhancements and use newer language features. These potential future investments may break the backwards compatibility with earlier VS versions - but we will be sure to inform our developers well ahead of such changes so that you can prepare. |
|||
|
|||
## Why change it |
|||
|
|||
* The use of Roslyn unblocks multithreaded serialization and deserialization to solve performance delays in designer load and unload scenarios. |
|||
* Code-behind generation now respects `.editorconfig` settings and thus matches code style in the source files. |
|||
* If implicit usings feature is enabled in project properties, global namespaces are not repeated in type names. |
|||
* Further modernization of code-behind is unblocked. |
|||
* Newly generated code will work with modern Roslyn analyzers. |
|||
|
|||
## How the new code looks like |
|||
|
|||
While `InitializeComponent` method is meant for the designer use only, and manual modifications to this method are not supported, developers might see some unexpected changes in `Form1.Designer.cs` and `Form1.designer.vb` files when comparing versions in the source control tools. This is a one-time code churn. Once the designer file is regenerated in v17.5 Preview 3 or newer and saved, designer will generate code only for controls modified in the design surface. |
|||
|
|||
For example, `InitializeComponent` method for a form with a button will be modified like this on the first save: |
|||
|
|||
 |
|||
|
|||
Code generated by VisualStudio v17.4 or earlier: |
|||
|
|||
```cs |
|||
private void InitializeComponent() |
|||
{ |
|||
this.button1 = new System.Windows.Forms.Button(); |
|||
this.SuspendLayout(); |
|||
// |
|||
// button1 |
|||
// |
|||
this.button1.Location = new System.Drawing.Point(58, 60); |
|||
this.button1.Name = "button1"; |
|||
this.button1.Size = new System.Drawing.Size(136, 69); |
|||
this.button1.TabIndex = 0; |
|||
this.button1.Text = "button1"; |
|||
this.button1.UseVisualStyleBackColor = true; |
|||
// |
|||
// Form1 |
|||
// |
|||
this.AutoScaleDimensions = new System.Drawing.SizeF(10F, 25F); |
|||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; |
|||
this.ClientSize = new System.Drawing.Size(270, 208); |
|||
this.Controls.Add(this.button1); |
|||
this.Name = "Form1"; |
|||
this.Text = "Form1"; |
|||
this.ResumeLayout(false); |
|||
|
|||
} |
|||
``` |
|||
|
|||
Code generated by VisualStudio v17.5 Preview 3, or newer: |
|||
|
|||
```cs |
|||
private void InitializeComponent() |
|||
{ |
|||
button1 = new Button(); |
|||
SuspendLayout(); |
|||
// |
|||
// button1 |
|||
// |
|||
button1.Location = new Point(58, 60); |
|||
button1.Name = "button1"; |
|||
button1.Size = new Size(136, 69); |
|||
button1.TabIndex = 0; |
|||
button1.Text = "button1"; |
|||
button1.UseVisualStyleBackColor = true; |
|||
// |
|||
// Form1 |
|||
// |
|||
AutoScaleDimensions = new SizeF(10F, 25F); |
|||
AutoScaleMode = AutoScaleMode.Font; |
|||
ClientSize = new Size(270, 208); |
|||
Controls.Add(button1); |
|||
Name = "Form1"; |
|||
Text = "Form1"; |
|||
ResumeLayout(false); |
|||
} |
|||
``` |
|||
|
|||
### Support for code style settings |
|||
|
|||
The above code was generated for default C# code style settings, thus `this` access qualifier was removed in the Preview 3 version. |
|||
|
|||
To preserve legacy code generation style in `InitializeComponent` method, set style preferences to legacy values in [`.editorconfig` file](https://learn.microsoft.com/visualstudio/ide/create-portable-custom-editor-options). |
|||
|
|||
```ini |
|||
[*.designer.cs] |
|||
|
|||
# this. preferences |
|||
dotnet_style_qualification_for_event = true |
|||
dotnet_style_qualification_for_field = true |
|||
dotnet_style_qualification_for_method = true |
|||
dotnet_style_qualification_for_property = true |
|||
|
|||
[*.vb] |
|||
|
|||
# Me. preferences |
|||
dotnet_style_qualification_for_event = true |
|||
dotnet_style_qualification_for_field = true |
|||
dotnet_style_qualification_for_method = true |
|||
dotnet_style_qualification_for_property = true |
|||
``` |
|||
|
|||
### Support for implicit usings property |
|||
|
|||
Namespace names were removed from the type names in Preview 3 version. They are not needed for type resolution because design time serialization looks up the [implicit usings](https://learn.microsoft.com/dotnet/core/tutorials/top-level-templates#implicit-using-directives) property, available in C# starting with .NET 6 for C#, from the project file: |
|||
|
|||
```xml |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<OutputType>WinExe</OutputType> |
|||
<TargetFramework>net8.0-windows</TargetFramework> |
|||
<Nullable>enable</Nullable> |
|||
<UseWindowsForms>true</UseWindowsForms> |
|||
<ImplicitUsings>enable</ImplicitUsings> |
|||
</PropertyGroup> |
|||
|
|||
</Project> |
|||
``` |
|||
|
|||
When implicit usings property is disabled in the C# project file, namespace names are generated. |
|||
|
|||
### Similar changes are present in Visual Basic |
|||
|
|||
 |
|||
|
|||
Code generated by VisualStudio v17.4 or earlier: |
|||
|
|||
```vb |
|||
<System.Diagnostics.DebuggerStepThrough()> |
|||
Private Sub InitializeComponent() |
|||
Me.Button1 = New System.Windows.Forms.Button() |
|||
Me.SuspendLayout() |
|||
' |
|||
'Button1 |
|||
' |
|||
Me.Button1.Location = New System.Drawing.Point(58, 60) |
|||
Me.Button1.Name = "Button1" |
|||
Me.Button1.Size = New System.Drawing.Size(136, 69) |
|||
Me.Button1.TabIndex = 0 |
|||
Me.Button1.Text = "Button1" |
|||
Me.Button1.UseVisualStyleBackColor = True |
|||
' |
|||
'Form1 |
|||
' |
|||
Me.AutoScaleDimensions = New System.Drawing.SizeF(10.0!, 25.0!) |
|||
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font |
|||
Me.ClientSize = New System.Drawing.Size(270, 208) |
|||
Me.Controls.Add(Me.Button1) |
|||
Me.Name = "Form1" |
|||
Me.Text = "Form1" |
|||
Me.ResumeLayout(False) |
|||
|
|||
End Sub |
|||
``` |
|||
|
|||
Code generated by VisualStudio v17.5 Preview 3, or newer: |
|||
|
|||
```vb |
|||
<System.Diagnostics.DebuggerStepThrough()> |
|||
Private Sub InitializeComponent() |
|||
Button1 = New Button() |
|||
SuspendLayout() |
|||
' |
|||
' Button1 |
|||
' |
|||
Button1.Location = New Point(58, 60) |
|||
Button1.Name = "Button1" |
|||
Button1.Size = New Size(136, 69) |
|||
Button1.TabIndex = 0 |
|||
Button1.Text = "Button1" |
|||
Button1.UseVisualStyleBackColor = True |
|||
' |
|||
' Form1 |
|||
' |
|||
AutoScaleDimensions = New SizeF(10.0F, 25.0F) |
|||
AutoScaleMode = AutoScaleMode.Font |
|||
ClientSize = New Size(270, 208) |
|||
Controls.Add(Button1) |
|||
Name = "Form1" |
|||
Text = "Form1" |
|||
ResumeLayout(False) |
|||
End Sub |
|||
``` |
|||
|
|||
## Summary |
|||
|
|||
New code-behind in WinForm apps looks differently because it follows code style settings defined for the project. Under the covers, the design time serialization was redesigned in order to move from `EnvDTE.CodeModel` to `Roslyn`. We are planning to build upon this foundation in the future Visual Studio releases. Code-behind generated by the older releases will load into v17.5 Preview 3 or later releases and will work as expected. Code-behind generated by v17.5 Preview 3 can be loaded in the previous releases of the Visual Studio, but we are considering generating modern code that might not be supported by the previous versions of deserializer. |
@ -1,11 +1,17 @@ |
|||
# Windows Forms Out-Of-Process Designer |
|||
|
|||
The Windows Forms Out-Of-Process Designer (or the OOP designer) is currently available as a pre-release Visual Studio feature in [Visual Studio 2019 or later](https://visualstudio.microsoft.com/vs/preview/). You can enable the OOP designer via **Tools -> Options -> Environment -> Preview Features** with **Use the preview Windows Forms designer for .NET Core apps**. |
|||
Releases of .NET Core Windows Forms Designer are tied to Visual Studio Preview releases, so update to the latest Visual Studio Preview version to get the latest designer features. |
|||
The Windows Forms out-of-process designer is currently available as a preview Visual Studio feature in [Visual Studio 2019 or later](https://visualstudio.microsoft.com/vs/preview/). It can be enabled in **Tools -> Options -> Environment -> Preview Features** dialog by checking the **Use the preview Windows Forms out-of-process designer for .NET apps** checkbox. |
|||
Releases of .NET Windows Forms Designer are tied to Visual Studio Preview releases, so update to the latest Visual Studio Preview version to get the newest designer features. |
|||
|
|||
For the latest news on the designer please refer to [the series of blogs](https://devblogs.microsoft.com/dotnet/state-of-the-windows-forms-designer-for-net-applications/) discussing the current state of the designer. |
|||
:heavy_exclamation_mark: The latest designer feature shipped in `Visual Studio 2022 v17.5 Preview 3` is [Modernization of code-behind generation](modernization-of-code-behind-in-oop-designer\modernization-of-code-behind-generation-in-oop-designer.md). |
|||
|
|||
For the latest news on the designer please refer to [the series of blogs](https://devblogs.microsoft.com/search?query=winforms&blog=%2Fdotnet%2F): |
|||
|
|||
* [State of the Windows Forms Designer for .NET Applications as of 01/13/2022](https://devblogs.microsoft.com/dotnet/state-of-the-windows-forms-designer-for-net-applications/) |
|||
* [Visual Basic WinForms Apps in .NET 5 and Visual Studio 16.8](https://devblogs.microsoft.com/dotnet/visual-basic-winforms-apps-in-net-5-and-visual-studio-16-8/) |
|||
* [Databinding with the OOP Windows Forms Designer](https://devblogs.microsoft.com/dotnet/databinding-with-the-oop-windows-forms-designer/) |
|||
|
|||
## Table of Content |
|||
|
|||
* [How to use .NET Framework designer for .NET applications](net-inproc-designer.md) |
|||
* [How to troubleshoot the OOP designer](troubleshooting.md) |
|||
* [How to troubleshoot the out-of-process designer](troubleshooting.md) |
Write
Preview
Loading…
Cancel
Save
Reference in new issue