From eef5611eed4482ab838e45572a753840de480522 Mon Sep 17 00:00:00 2001 From: "Andy De George (adegeo)" Date: Tue, 5 Dec 2023 13:57:14 -0800 Subject: [PATCH 1/4] Add WinForms whatsnew --- dotnet-desktop-guide/net/winforms/toc.yml | 2 + .../whats-new/media/net80/commands.png | Bin 0 -> 5856 bytes .../net/winforms/whats-new/net70.md | 2 +- .../net/winforms/whats-new/net80.md | 95 ++++++++++++ .../snippets/net80/csharp/Company.cs | 29 ++++ .../csharp/DataBindingExample.Designer.cs | 121 +++++++++++++++ .../net80/csharp/DataBindingExample.cs | 35 +++++ .../net80/csharp/DataBindingExample.resx | 123 +++++++++++++++ .../snippets/net80/csharp/Form1.Designer.cs | 144 ++++++++++++++++++ .../whats-new/snippets/net80/csharp/Form1.cs | 16 ++ .../snippets/net80/csharp/Form1.resx | 120 +++++++++++++++ .../snippets/net80/csharp/Program.cs | 16 ++ .../Properties/DataSources/Company.datasource | 10 ++ .../snippets/net80/csharp/snippets.csproj | 18 +++ 14 files changed, 730 insertions(+), 1 deletion(-) create mode 100644 dotnet-desktop-guide/net/winforms/whats-new/media/net80/commands.png create mode 100644 dotnet-desktop-guide/net/winforms/whats-new/net80.md create mode 100644 dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Company.cs create mode 100644 dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/DataBindingExample.Designer.cs create mode 100644 dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/DataBindingExample.cs create mode 100644 dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/DataBindingExample.resx create mode 100644 dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Form1.Designer.cs create mode 100644 dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Form1.cs create mode 100644 dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Form1.resx create mode 100644 dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Program.cs create mode 100644 dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Properties/DataSources/Company.datasource create mode 100644 dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/snippets.csproj diff --git a/dotnet-desktop-guide/net/winforms/toc.yml b/dotnet-desktop-guide/net/winforms/toc.yml index ce41f7c774..28ebda2d2c 100644 --- a/dotnet-desktop-guide/net/winforms/toc.yml +++ b/dotnet-desktop-guide/net/winforms/toc.yml @@ -3,6 +3,8 @@ items: href: index.yml - name: What's new items: + - name: What's new in .NET 8.0 + href: whats-new/net80.md - name: What's new in .NET 7.0 href: whats-new/net70.md - name: What's new in .NET 6.0 diff --git a/dotnet-desktop-guide/net/winforms/whats-new/media/net80/commands.png b/dotnet-desktop-guide/net/winforms/whats-new/media/net80/commands.png new file mode 100644 index 0000000000000000000000000000000000000000..c9a6e94ff8065513ee845e8e0c6c31f0c23b3a5a GIT binary patch literal 5856 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 property in your project file: + +```xml + + + + + + Microsoft Sans Serif, 8.25pt + + + +``` + +The Visual Studio designer respects the application's default font when it's set in the project file. + +## Data binding improvements + +A new data binding engine was in preview with .NET 7, and is now fully enabled in .NET 8. Though not as extensive as the existing Windows Forms data binding engine, this new engine is modeled after WPF, which makes it easier to implement MVVM design principles. + +The enhanced data binding capabilities now make it simpler to fully utilize the MVVM pattern and employ object-relational mappers from ViewModels in Windows Forms. This reduces the amount of code in code-behind files. More importantly, it enables code sharing between Windows Forms and other .NET GUI frameworks like WPF, UWP/WinUI, and .NET MAUI. It's important to note that while the previously mentioned GUI frameworks use XAML as a UI technology, XAML isn't coming to Windows Forms. + +The interface and the class drive the new binding system. implements the interface and provides new data binding capabilities to Windows Forms. + +## Button commands + +Button commands were in preview with .NET 7, and is now fully enabled in .NET 8. Similar to WPF, the instance of an object that implements the interface can be assigned to the button's property. When the button is clicked, the command is invoked. + +An optional parameter can be sent to the command by the specifying a value for the button's property. + +The `Command` and `CommandParameter` properties are set in the designer through the **Properties** window, under **(DataBindings)**, as illustrated by the following image. + +:::image type="content" source="media/net80/commands.png" alt-text="The Visual Studio properties window highlighting a Windows Forms' Button's Command and CommandParameter properties."::: + +Buttons also listen to the event, which causes the control to query the method. When that method returns `true`, the control is enabled; the control is disabled when `false`is returned. + +## Visual Studio DPI improvments + +Visual Studio 2022 17.8 Introduces DPI-unwaware designer tabs. Previously, the Windows Designer tab in Visual Studio ran at the DPI of Visual Studio. This causes problems when you're designing a DPI-unaware Windows Forms app. Now you can ensure that the designer runs at the same scale as you want the app to run, either DPI-aware or not. Before this feature was introduced, you had to run Visual Studio as DPI-unaware whic made Visual Studio itself blurry when scaling was applied to + +This setting is controlled by the `` project setting. Set this to `true` to force the designer to be DPI-unaware. + +:::code language="xml" source="./snippets/net80/csharp/snippets.csproj" range="3-11" highlight="7"::: + +> [!IMPORTANT] +> After changing this setting, you must unload and reload your project to get Visual Studio to respect it.s + +## High DPI improvements + +High DPI rendering with has been improved: + +- Correctly scale nested controls. For example, a button that's in a panel, which is placed on a tab page. +- Scale and properties based on the current monitor DPI settings. + + Starting with .NET 8, this feature is enabled by default and you need to opt out of it to revert to the previous behavior. + + To disable the feature, add `System.Windows.Forms.ScaleTopLevelFormMinMaxSizeForDpi` to the `configProperties` setting in [_runtimeconfig.json_](/dotnet/core/runtime-config/#runtimeconfigjson), and set the value to false: + + ```json + { + "runtimeOptions": { + "tfm": "net8.0", + "frameworks": [ + ... + ], + "configProperties": { + "System.Windows.Forms.ScaleTopLevelFormMinMaxSizeForDpi": false, + } + } + } + ``` + +## Miscellaneous improvements + +Here are some other notable changes: + +- The code that handled `FolderBrowserDialog` was improved, fixing a few memory leaks. +- The code base for Windows Forms has been slowly enabling C# nullability, rooting out any potential null-reference errors. diff --git a/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Company.cs b/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Company.cs new file mode 100644 index 0000000000..5661dd1320 --- /dev/null +++ b/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Company.cs @@ -0,0 +1,29 @@ +using System.Windows.Input; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; + +namespace snippets; + +public class Company: ObservableObject +{ + int _employeeCount = 10; + + public int EmployeeCount + { + get => _employeeCount; + set => SetProperty(ref _employeeCount, value); + } + + public ICommand IncreaseEmployeeCommand { get; } + + public Company() + { + IncreaseEmployeeCommand = new RelayCommand(IncreaseEmployeeCount, (i) => EmployeeCount < 20); + } + + private void IncreaseEmployeeCount(int count) + { + EmployeeCount += count; + ((RelayCommand)IncreaseEmployeeCommand).NotifyCanExecuteChanged(); + } +} diff --git a/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/DataBindingExample.Designer.cs b/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/DataBindingExample.Designer.cs new file mode 100644 index 0000000000..15405611fe --- /dev/null +++ b/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/DataBindingExample.Designer.cs @@ -0,0 +1,121 @@ +namespace snippets +{ + partial class DataBindingExample + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + components = new System.ComponentModel.Container(); + button1 = new Button(); + companyBindingSource = new BindingSource(components); + label1 = new Label(); + label2 = new Label(); + btnCompany1 = new Button(); + btnCompany2 = new Button(); + ((System.ComponentModel.ISupportInitialize)companyBindingSource).BeginInit(); + SuspendLayout(); + // + // button1 + // + button1.DataBindings.Add(new Binding("Command", companyBindingSource, "IncreaseEmployeeCommand", true)); + button1.Location = new Point(12, 12); + button1.Name = "button1"; + button1.Size = new Size(170, 23); + button1.TabIndex = 0; + button1.Text = "Increase Employee Count"; + button1.UseVisualStyleBackColor = true; + // + // companyBindingSource + // + companyBindingSource.DataSource = typeof(Company); + // + // label1 + // + label1.AutoSize = true; + label1.Location = new Point(12, 45); + label1.Name = "label1"; + label1.Size = new Size(98, 15); + label1.TabIndex = 1; + label1.Text = "Employee Count:"; + // + // label2 + // + label2.AutoSize = true; + label2.DataBindings.Add(new Binding("Text", companyBindingSource, "EmployeeCount", true)); + label2.Location = new Point(116, 45); + label2.Name = "label2"; + label2.Size = new Size(13, 15); + label2.TabIndex = 2; + label2.Text = "0"; + // + // btnCompany1 + // + btnCompany1.Location = new Point(12, 123); + btnCompany1.Name = "btnCompany1"; + btnCompany1.Size = new Size(207, 23); + btnCompany1.TabIndex = 3; + btnCompany1.Text = "Load Company 1 (10 employess)"; + btnCompany1.UseVisualStyleBackColor = true; + btnCompany1.Click += btnCompany1_Click; + // + // btnCompany2 + // + btnCompany2.Location = new Point(12, 152); + btnCompany2.Name = "btnCompany2"; + btnCompany2.Size = new Size(207, 23); + btnCompany2.TabIndex = 4; + btnCompany2.Text = "Load Company 2 (3 employess)"; + btnCompany2.UseVisualStyleBackColor = true; + btnCompany2.Click += btnCompany2_Click; + // + // DataBindingExample + // + AutoScaleDimensions = new SizeF(7F, 15F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(238, 192); + Controls.Add(btnCompany2); + Controls.Add(btnCompany1); + Controls.Add(label2); + Controls.Add(label1); + Controls.Add(button1); + Name = "DataBindingExample"; + Text = "DataBindingExample"; + DataContextChanged += DataBindingExample_DataContextChanged; + ((System.ComponentModel.ISupportInitialize)companyBindingSource).EndInit(); + ResumeLayout(false); + PerformLayout(); + } + + #endregion + + private Button button1; + private Label label1; + private Label label2; + private BindingSource companyBindingSource; + private Button btnCompany1; + private Button btnCompany2; + } +} diff --git a/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/DataBindingExample.cs b/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/DataBindingExample.cs new file mode 100644 index 0000000000..5dfd313fb0 --- /dev/null +++ b/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/DataBindingExample.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace snippets +{ + public partial class DataBindingExample : Form + { + public DataBindingExample() + { + InitializeComponent(); + button1.CommandParameter = 5; + } + + private void DataBindingExample_DataContextChanged(object sender, EventArgs e) => + companyBindingSource.DataSource = DataContext; + + private void btnCompany1_Click(object sender, EventArgs e) + { + DataContext = new Company() { EmployeeCount = 10 }; + + } + + private void btnCompany2_Click(object sender, EventArgs e) + { + DataContext = new Company() { EmployeeCount = 3 }; + } + } +} diff --git a/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/DataBindingExample.resx b/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/DataBindingExample.resx new file mode 100644 index 0000000000..6915fcb700 --- /dev/null +++ b/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/DataBindingExample.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Form1.Designer.cs b/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Form1.Designer.cs new file mode 100644 index 0000000000..07a786dfd0 --- /dev/null +++ b/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Form1.Designer.cs @@ -0,0 +1,144 @@ +namespace snippets; + +partial class Form1 +{ + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + button1 = new Button(); + checkBox1 = new CheckBox(); + dateTimePicker1 = new DateTimePicker(); + richTextBox1 = new RichTextBox(); + label1 = new Label(); + label2 = new Label(); + label3 = new Label(); + label4 = new Label(); + SuspendLayout(); + // + // button1 + // + button1.Location = new Point(12, 12); + button1.Name = "button1"; + button1.Size = new Size(75, 23); + button1.TabIndex = 0; + button1.Text = "button1"; + button1.UseVisualStyleBackColor = true; + button1.Click += button1_Click; + // + // checkBox1 + // + checkBox1.AutoSize = true; + checkBox1.Location = new Point(12, 41); + checkBox1.Name = "checkBox1"; + checkBox1.Size = new Size(83, 19); + checkBox1.TabIndex = 1; + checkBox1.Text = "checkBox1"; + checkBox1.UseVisualStyleBackColor = true; + // + // dateTimePicker1 + // + dateTimePicker1.Location = new Point(12, 66); + dateTimePicker1.Name = "dateTimePicker1"; + dateTimePicker1.ShowCheckBox = true; + dateTimePicker1.Size = new Size(208, 23); + dateTimePicker1.TabIndex = 2; + // + // richTextBox1 + // + richTextBox1.Location = new Point(226, 34); + richTextBox1.Name = "richTextBox1"; + richTextBox1.Size = new Size(167, 55); + richTextBox1.TabIndex = 3; + richTextBox1.Text = ""; + // + // label1 + // + label1.AutoSize = true; + label1.Location = new Point(226, 16); + label1.Name = "label1"; + label1.Size = new Size(106, 15); + label1.TabIndex = 4; + label1.Text = "RichTextBox below"; + // + // label2 + // + label2.AutoSize = true; + label2.Font = new Font("Segoe UI Variable Display", 9F, FontStyle.Regular, GraphicsUnit.Point); + label2.Location = new Point(12, 92); + label2.Name = "label2"; + label2.Size = new Size(75, 16); + label2.TabIndex = 5; + label2.Text = "Font preview"; + // + // label3 + // + label3.AutoSize = true; + label3.Font = new Font("Segoe UI", 9F, FontStyle.Regular, GraphicsUnit.Point); + label3.Location = new Point(12, 107); + label3.Name = "label3"; + label3.Size = new Size(75, 15); + label3.TabIndex = 6; + label3.Text = "Font preview"; + // + // label4 + // + label4.AutoSize = true; + label4.Location = new Point(12, 122); + label4.Name = "label4"; + label4.Size = new Size(75, 15); + label4.TabIndex = 7; + label4.Text = "Font preview"; + // + // Form1 + // + AutoScaleDimensions = new SizeF(7F, 15F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(403, 161); + Controls.Add(label4); + Controls.Add(label3); + Controls.Add(label2); + Controls.Add(label1); + Controls.Add(richTextBox1); + Controls.Add(dateTimePicker1); + Controls.Add(checkBox1); + Controls.Add(button1); + Name = "Form1"; + Text = "Form1"; + ResumeLayout(false); + PerformLayout(); + } + + #endregion + + private Button button1; + private CheckBox checkBox1; + private DateTimePicker dateTimePicker1; + private RichTextBox richTextBox1; + private Label label1; + private Label label2; + private Label label3; + private Label label4; +} diff --git a/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Form1.cs b/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Form1.cs new file mode 100644 index 0000000000..1c93ab9832 --- /dev/null +++ b/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Form1.cs @@ -0,0 +1,16 @@ +namespace snippets; + +public partial class Form1 : Form +{ + public Form1() + { + InitializeComponent(); + } + + private void button1_Click(object sender, EventArgs e) + { + FolderBrowserDialog dialog = new FolderBrowserDialog(); + dialog.ShowDialog(); + + } +} diff --git a/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Form1.resx b/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Form1.resx new file mode 100644 index 0000000000..af32865ec1 --- /dev/null +++ b/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Form1.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Program.cs b/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Program.cs new file mode 100644 index 0000000000..1803f47b28 --- /dev/null +++ b/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Program.cs @@ -0,0 +1,16 @@ +namespace snippets; + +static class Program +{ + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + // To customize application configuration such as set high DPI settings or default font, + // see https://aka.ms/applicationconfiguration. + ApplicationConfiguration.Initialize(); + Application.Run(new DataBindingExample()); + } +} diff --git a/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Properties/DataSources/Company.datasource b/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Properties/DataSources/Company.datasource new file mode 100644 index 0000000000..826f98118a --- /dev/null +++ b/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Properties/DataSources/Company.datasource @@ -0,0 +1,10 @@ + + + + snippets.Company, snippets, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + \ No newline at end of file diff --git a/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/snippets.csproj b/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/snippets.csproj new file mode 100644 index 0000000000..51aab9f023 --- /dev/null +++ b/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/snippets.csproj @@ -0,0 +1,18 @@ + + + + WinExe + net8.0-windows + enable + true + enable + false + DpiUnawareGdiScaled + + + + + + + + \ No newline at end of file From 33bde1f88a5d198d133a501686a86e12716d1fdf Mon Sep 17 00:00:00 2001 From: "Andy De George (adegeo)" Date: Tue, 5 Dec 2023 14:08:05 -0800 Subject: [PATCH 2/4] updates --- dotnet-desktop-guide/net/winforms/whats-new/net80.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dotnet-desktop-guide/net/winforms/whats-new/net80.md b/dotnet-desktop-guide/net/winforms/whats-new/net80.md index 781e326074..3efbccea39 100644 --- a/dotnet-desktop-guide/net/winforms/whats-new/net80.md +++ b/dotnet-desktop-guide/net/winforms/whats-new/net80.md @@ -13,7 +13,7 @@ There are a few breaking changes you should be aware of when migrating from .NET ## New default font -The default font is now the same as your Windows default font. This may affect the control layout used in your forms and controls. Previous versions of Windows Forms for .NET had changed the default font to **Segoe UI, 9pt**. Windows Forms for .NET Framework continues to use **Microsoft Sans Serif, 8.25pt** as the default font. +The default font is now the same as your Windows default font. This might affect the control layout used in your forms and controls. Previous versions of Windows Forms for .NET changed the default font to **Segoe UI, 9pt**. Windows Forms for .NET Framework uses **Microsoft Sans Serif, 8.25pt** as the default font. If the font change affects the layout of your forms, and you don't want to adjust them, you can revert to either the older default .NET font or the default .NET Framework font by setting the `` property in your project file: @@ -29,7 +29,7 @@ If the font change affects the layout of your forms, and you don't want to adjus ``` -The Visual Studio designer respects the application's default font when it's set in the project file. +The Visual Studio designer respects the application's default font when set in the project file. ## Data binding improvements @@ -43,7 +43,7 @@ The interface and the interface can be assigned to the button's property. When the button is clicked, the command is invoked. -An optional parameter can be sent to the command by the specifying a value for the button's property. +An optional parameter can be provided when the command is invoked, by the specifying a value for the button's property. The `Command` and `CommandParameter` properties are set in the designer through the **Properties** window, under **(DataBindings)**, as illustrated by the following image. @@ -51,11 +51,11 @@ The `Command` and `CommandParameter` properties are set in the designer through Buttons also listen to the event, which causes the control to query the method. When that method returns `true`, the control is enabled; the control is disabled when `false`is returned. -## Visual Studio DPI improvments +## Visual Studio DPI improvements -Visual Studio 2022 17.8 Introduces DPI-unwaware designer tabs. Previously, the Windows Designer tab in Visual Studio ran at the DPI of Visual Studio. This causes problems when you're designing a DPI-unaware Windows Forms app. Now you can ensure that the designer runs at the same scale as you want the app to run, either DPI-aware or not. Before this feature was introduced, you had to run Visual Studio as DPI-unaware whic made Visual Studio itself blurry when scaling was applied to +Visual Studio 2022 17.8 Introduces DPI-unwaware designer tabs. Previously, the Windows Designer tab in Visual Studio ran at the DPI of Visual Studio. This causes problems when you're designing a DPI-unaware Windows Forms app. Now you can ensure that the designer runs at the same scale as you want the app to run, either DPI-aware or not. Before this feature was introduced, you had to run Visual Studio in DPI-unaware mode, which made Visual Studio itself blurry when scaling was applied in Windows. Now you can leave Visual Studio alone and let the designer run DPI-unaware. -This setting is controlled by the `` project setting. Set this to `true` to force the designer to be DPI-unaware. +You can force the DPI-unaware designer by adding the `` project setting and setting the value to `true`. :::code language="xml" source="./snippets/net80/csharp/snippets.csproj" range="3-11" highlight="7"::: From 72f8192a2f0d1ff9e4b60178352c7a82949eef99 Mon Sep 17 00:00:00 2001 From: "Andy De George (adegeo)" Date: Tue, 5 Dec 2023 16:47:57 -0800 Subject: [PATCH 3/4] feedback;fixes --- .../net/winforms/whats-new/net80.md | 29 ++++--------------- .../snippets/net80/csharp/Company.cs | 16 +++++++++- .../csharp/DataBindingExample.Designer.cs | 14 +++++++++ 3 files changed, 35 insertions(+), 24 deletions(-) diff --git a/dotnet-desktop-guide/net/winforms/whats-new/net80.md b/dotnet-desktop-guide/net/winforms/whats-new/net80.md index 3efbccea39..48f9868fe7 100644 --- a/dotnet-desktop-guide/net/winforms/whats-new/net80.md +++ b/dotnet-desktop-guide/net/winforms/whats-new/net80.md @@ -11,31 +11,11 @@ This article describes some of the new Windows Forms features and enhancements i There are a few breaking changes you should be aware of when migrating from .NET Framework to .NET 8. For more information, see [Breaking changes in Windows Forms](/dotnet/core/compatibility/winforms). -## New default font - -The default font is now the same as your Windows default font. This might affect the control layout used in your forms and controls. Previous versions of Windows Forms for .NET changed the default font to **Segoe UI, 9pt**. Windows Forms for .NET Framework uses **Microsoft Sans Serif, 8.25pt** as the default font. - -If the font change affects the layout of your forms, and you don't want to adjust them, you can revert to either the older default .NET font or the default .NET Framework font by setting the `` property in your project file: - -```xml - - - - - - Microsoft Sans Serif, 8.25pt - - - -``` - -The Visual Studio designer respects the application's default font when set in the project file. - ## Data binding improvements A new data binding engine was in preview with .NET 7, and is now fully enabled in .NET 8. Though not as extensive as the existing Windows Forms data binding engine, this new engine is modeled after WPF, which makes it easier to implement MVVM design principles. -The enhanced data binding capabilities now make it simpler to fully utilize the MVVM pattern and employ object-relational mappers from ViewModels in Windows Forms. This reduces the amount of code in code-behind files. More importantly, it enables code sharing between Windows Forms and other .NET GUI frameworks like WPF, UWP/WinUI, and .NET MAUI. It's important to note that while the previously mentioned GUI frameworks use XAML as a UI technology, XAML isn't coming to Windows Forms. +The enhanced data binding capabilities make it simpler to fully utilize the MVVM pattern and employ object-relational mappers from ViewModels in Windows Forms. This reduces the amount of code in code-behind files. More importantly, it enables code sharing between Windows Forms and other .NET GUI frameworks like WPF, UWP/WinUI, and .NET MAUI. It's important to note that while the previously mentioned GUI frameworks use XAML as a UI technology, XAML isn't coming to Windows Forms. The interface and the class drive the new binding system. implements the interface and provides new data binding capabilities to Windows Forms. @@ -55,12 +35,12 @@ Buttons also listen to the ` project setting and setting the value to `true`. +You can enable the DPI-unaware designer for the Windows Forms project by adding `` to the project file, and setting the value to `true`. :::code language="xml" source="./snippets/net80/csharp/snippets.csproj" range="3-11" highlight="7"::: > [!IMPORTANT] -> After changing this setting, you must unload and reload your project to get Visual Studio to respect it.s +> After changing this setting, you must unload and reload your project to get Visual Studio to respect it. ## High DPI improvements @@ -93,3 +73,6 @@ Here are some other notable changes: - The code that handled `FolderBrowserDialog` was improved, fixing a few memory leaks. - The code base for Windows Forms has been slowly enabling C# nullability, rooting out any potential null-reference errors. +- The `System.Drawing` source code was migrated to the [Windows Forms GitHub repository](https://github.com/dotnet/winforms). +- Modern Windows icons can be accessed by a new API, . The enumeration lists all of the available system icons. +- More designers are available at run-time now. For more information, see [GitHub issue #4908](https://github.com/dotnet/winforms/issues/4908). diff --git a/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Company.cs b/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Company.cs index 5661dd1320..3d7c337e6b 100644 --- a/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Company.cs +++ b/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/Company.cs @@ -4,9 +4,13 @@ namespace snippets; -public class Company: ObservableObject +public class Company: ObservableObject, IDisposable { int _employeeCount = 10; + //Bitmap _icon = SystemIcons.GetStockIcon(StockIconId.Warning, StockIconOptions.Default).ToBitmap(); + Bitmap _icon = SystemIcons.Warning.ToBitmap(); + + public Bitmap CompanyImage => _icon; public int EmployeeCount { @@ -16,6 +20,11 @@ public int EmployeeCount public ICommand IncreaseEmployeeCommand { get; } + ~Company() + { + Dispose(); + } + public Company() { IncreaseEmployeeCommand = new RelayCommand(IncreaseEmployeeCount, (i) => EmployeeCount < 20); @@ -26,4 +35,9 @@ private void IncreaseEmployeeCount(int count) EmployeeCount += count; ((RelayCommand)IncreaseEmployeeCommand).NotifyCanExecuteChanged(); } + + public void Dispose() + { + _icon.Dispose(); + } } diff --git a/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/DataBindingExample.Designer.cs b/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/DataBindingExample.Designer.cs index 15405611fe..70c5424c9a 100644 --- a/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/DataBindingExample.Designer.cs +++ b/dotnet-desktop-guide/net/winforms/whats-new/snippets/net80/csharp/DataBindingExample.Designer.cs @@ -35,7 +35,9 @@ private void InitializeComponent() label2 = new Label(); btnCompany1 = new Button(); btnCompany2 = new Button(); + pictureBox1 = new PictureBox(); ((System.ComponentModel.ISupportInitialize)companyBindingSource).BeginInit(); + ((System.ComponentModel.ISupportInitialize)pictureBox1).BeginInit(); SuspendLayout(); // // button1 @@ -91,11 +93,21 @@ private void InitializeComponent() btnCompany2.UseVisualStyleBackColor = true; btnCompany2.Click += btnCompany2_Click; // + // pictureBox1 + // + pictureBox1.DataBindings.Add(new Binding("Image", companyBindingSource, "CompanyImage", true)); + pictureBox1.Location = new Point(12, 67); + pictureBox1.Name = "pictureBox1"; + pictureBox1.Size = new Size(100, 50); + pictureBox1.TabIndex = 5; + pictureBox1.TabStop = false; + // // DataBindingExample // AutoScaleDimensions = new SizeF(7F, 15F); AutoScaleMode = AutoScaleMode.Font; ClientSize = new Size(238, 192); + Controls.Add(pictureBox1); Controls.Add(btnCompany2); Controls.Add(btnCompany1); Controls.Add(label2); @@ -105,6 +117,7 @@ private void InitializeComponent() Text = "DataBindingExample"; DataContextChanged += DataBindingExample_DataContextChanged; ((System.ComponentModel.ISupportInitialize)companyBindingSource).EndInit(); + ((System.ComponentModel.ISupportInitialize)pictureBox1).EndInit(); ResumeLayout(false); PerformLayout(); } @@ -117,5 +130,6 @@ private void InitializeComponent() private BindingSource companyBindingSource; private Button btnCompany1; private Button btnCompany2; + private PictureBox pictureBox1; } } From a5435e4b76aef8e39818bafc1b9c8e46aec5a261 Mon Sep 17 00:00:00 2001 From: "Andy (Steve) De George" <67293991+adegeo@users.noreply.github.com> Date: Thu, 7 Dec 2023 15:01:01 -0800 Subject: [PATCH 4/4] Update dotnet-desktop-guide/net/winforms/whats-new/net80.md --- dotnet-desktop-guide/net/winforms/whats-new/net80.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet-desktop-guide/net/winforms/whats-new/net80.md b/dotnet-desktop-guide/net/winforms/whats-new/net80.md index 48f9868fe7..85ebe62e8a 100644 --- a/dotnet-desktop-guide/net/winforms/whats-new/net80.md +++ b/dotnet-desktop-guide/net/winforms/whats-new/net80.md @@ -40,7 +40,7 @@ You can enable the DPI-unaware designer for the Windows Forms project by adding :::code language="xml" source="./snippets/net80/csharp/snippets.csproj" range="3-11" highlight="7"::: > [!IMPORTANT] -> After changing this setting, you must unload and reload your project to get Visual Studio to respect it. +> Visual Studio reads this setting when the project is loaded, and not when it's changed. After changing this setting, unload and reload your project to get Visual Studio to respect it. ## High DPI improvements