.NET 7 Windows 窗体中的新增功能

本文介绍 .NET 7 中一些新的 Windows 窗体功能和增强功能。

从 .NET Framework 迁移到 .NET 7 时,应注意一些中断性变更。 有关详细信息,请参阅 Windows 窗体中的重大更改

高 DPI 改进

改进了 PerMonitorV2 的高 DPI 呈现:

  • 正确缩放嵌套控件。 例如,一个在面板上的按钮,放置在一个选项卡页上。

  • 根据运行 Form.MaximumSize 设置为 Form.MinimumSize 的应用程序的当前监视器 DPI 设置,缩放 ApplicationHighDpiModePerMonitorV2 属性。

    在 .NET 7 中,此功能默认处于禁用状态,必须选择加入才能接收此更改。 从 .NET 8 开始,此功能默认启用,你需要选择退出此功能,才能还原以前的行为。

    若要启用功能,请在 runtimeconfig.jsonconfigProperties 中设置 设置:

    {
      "runtimeOptions": {
        "tfm": "net7.0",
        "frameworks": [
            ...
        ],
        "configProperties": {
          "System.Windows.Forms.ScaleTopLevelFormMinMaxSizeForDpi": true,
        }
      }
    }
    

辅助功能改进和修复

此版本进一步改进了辅助功能,包括但不限于以下项:

数据绑定改进(预览版)

虽然 Windows 窗体已经有一个功能强大的绑定引擎,但正在引入一种更现代化的数据绑定形式,类似于 WPF 提供的数据绑定。

借助新的数据绑定功能,可以完全采用 MVVM 模式,并在 Windows 窗体中比以往更轻松地使用 ViewModels 中的对象关系映射器。 这反过来又可以减少代码隐藏文件中的代码,开辟了新的测试可能性。 更重要的是,它支持 Windows 窗体和其他 .NET GUI 框架(如 WPF、UWP/WinUI 和 NET MAUI)之间的代码共享。 澄清一个常见问题,目前还没有在 Windows 窗体中引入 XAML 的任何计划。

这些新的数据绑定功能在 .NET 7 中处于预览状态,而有关此功能的更多工作将在 .NET 8 中开展。

若要启用新绑定,请将 EnablePreviewFeatures 设置添加到项目文件。 C# 和 Visual Basic 都支持此操作。

<Project Sdk="Microsoft.NET.Sdk">

  <!-- other settings -->

  <PropertyGroup>
    <EnablePreviewFeatures>true</EnablePreviewFeatures>
  </PropertyGroup>

</Project>

以下代码片段演示了添加到 Windows 窗体中的各种类的新属性、事件和方法。 即使以下代码示例采用 C#,它也适用于 Visual Basic。

public class Control  {
    [BindableAttribute(true)]
    public virtual object DataContext { get; set; }
    [BrowsableAttribute(true)]
    public event EventHandler DataContextChanged;
    protected virtual void OnDataContextChanged(EventArgs e);
    protected virtual void OnParentDataContextChanged(EventArgs e);
}

[RequiresPreviewFeaturesAttribute]
public abstract class BindableComponent : Component, IBindableComponent, IComponent, IDisposable {
    protected BindableComponent();
    public BindingContext? BindingContext { get; set; }
    public ControlBindingsCollection DataBindings { get; }
    public event EventHandler BindingContextChanged;
    protected virtual void OnBindingContextChanged(EventArgs e);
}

public abstract class ButtonBase : Control {
    [BindableAttribute(true)]
    [RequiresPreviewFeaturesAttribute]
    public ICommand? Command { get; set; }
    [BindableAttribute(true)]
    public object? CommandParameter { [RequiresPreviewFeaturesAttribute] get; [RequiresPreviewFeaturesAttribute] set; }
    [RequiresPreviewFeaturesAttribute]
    public event EventHandler? CommandCanExecuteChanged;
    [RequiresPreviewFeaturesAttribute]
    public event EventHandler? CommandChanged;
    [RequiresPreviewFeaturesAttribute]
    public event EventHandler? CommandParameterChanged;
    [RequiresPreviewFeaturesAttribute]
    protected virtual void OnCommandCanExecuteChanged(EventArgs e);
    [RequiresPreviewFeaturesAttribute]
    protected virtual void OnCommandChanged(EventArgs e);
    [RequiresPreviewFeaturesAttribute]
    protected virtual void OnCommandParameterChanged(EventArgs e);
    [RequiresPreviewFeaturesAttribute]
    protected virtual void OnRequestCommandExecute(EventArgs e);
}

public abstract class ToolStripItem : BindableComponent, IComponent, IDisposable, IDropTarget {
    [BindableAttribute(true)]
    [RequiresPreviewFeaturesAttribute]
    public ICommand Command { get; set; }
    [BindableAttribute(true)]
    public object CommandParameter { [RequiresPreviewFeaturesAttribute] get; [RequiresPreviewFeaturesAttribute] set; }
    [RequiresPreviewFeaturesAttribute]
    public event EventHandler CommandCanExecuteChanged;
    [RequiresPreviewFeaturesAttribute]
    public event EventHandler CommandChanged;
    [RequiresPreviewFeaturesAttribute]
    public event EventHandler CommandParameterChanged;
    [RequiresPreviewFeaturesAttribute]
    protected virtual void OnCommandCanExecuteChanged(EventArgs e);
    [RequiresPreviewFeaturesAttribute]
    protected virtual void OnCommandChanged(EventArgs e);
    [RequiresPreviewFeaturesAttribute]
    protected virtual void OnCommandParameterChanged(EventArgs e);
    [RequiresPreviewFeaturesAttribute]
    protected virtual void OnRequestCommandExecute(EventArgs e);
}

其他改进

下面是一些其他值得注意的变更:

  • 拖放处理与 Windows 拖放功能一致,具有更丰富的显示效果,如图标和文本标签。
  • 文件夹和文件对话框允许使用更多选项:
    • 添加到最近
    • 检查写入访问权限
    • 展开模式
    • “确定”需要交互
    • 选择“只读”
    • 显示隐藏文件
    • 显示固定位置
    • 显示预览
  • ErrorProvider 现在有一个 HasErrors 属性。
  • 窗体的贴靠布局已针对 Windows 11 进行了修复。

另请参阅