2023年2月23日

更新了WinForm的InitializeComponent的现代代码生成

克劳斯·洛夫曼
高级软件工程师

使用中的WinForms设计器创建WinForms窗体或用户控件时Visual Studio,它没有像XML或HTML来表示用户界面。从一开始,唯一的格式WinForms使用的是程序代码。WinForms中定义的窗体或用户控件Visual Basic项目保存到VB代码中。在C#项目中,这就是C#代码。该代码将放置在专用的Designer文件中,该文件位于实际窗体代码文件,并包含用于控制UI的代码。

解决方案资源管理器中设计器文件背后的WinForms Form代码的屏幕截图

当需要在WinForms中再次打开窗体或用户控件时设计器,该代码将被解释,并基于生成的对象图在设计器中重新创建窗体/用户控件。这就是我们打电话的原因保存表单的过程CodeDOM序列化.代码DOM这里指的是对象模型(代码D类文件O(运行)对象M(M)模型)它允许开发人员定义程序的各个方面或程序的一部分通过特定类型的对象。

带有按钮的WinForms窗体的屏幕截图以及InitializeComponent中各自生成的代码

虽然CodeDOM非常灵活,但可以相对轻松地进行扩展支持比Visual Basic或C#更多的语言,从中生成CodeDOM图现有的代码文件完全不同。尽管CodeDOM为特定语言实际编写代码文件的选项其现有编译器实施,结果代码的样式与.NET Framework,在许多情况下不再符合当前的编码标准。

在WinForms中,当您设计窗体时,会生成所有相关的内容每个窗体或用户控件使用一种方法。这种方法(在一些基础结构和初始化代码)初始化组件.

此方法由Form的构造函数无条件调用。在C#情况下这很明显,您添加到项目中的新表单总是具有该构造函数和所需的调用:

公共部分类Form1:Form{公共窗体2(){InitializeComponent();}}

在Visual Basic中,如果不添加构造函数Sub新建明确地说基本编译器插入对初始化组件在中自动背景。但是,如果向代码文件中添加构造函数,编辑器也会将呼叫插入初始化组件在VB代码中:

公开课表格1新建子项()'此调用是设计器所必需的。初始化组件()'在InitializeComponent()调用后添加任何初始化。结束Sub结束类

请注意,在Visual Basic中继承语句,它允许您的新窗体类继承自系统。窗户。形式。形式基类,与C相反#只是设计器代码隐藏文件的一部分。在VB中,对于分部类只声明部分关键字在一个分部类的代码文件中。这就是为什么要使用Visual BasicWinForms窗体代码文件只包含窗体的类默认情况下定义。

直到最近,WinForms Designer使用代码模型接口解释不同编程语言的源代码以构建设计器保存窗体或用户所需的内部CodeDOM图控件的定义。但我们改变了这一点。

进入Roslyn

WinForms与Visual Studio 2022版本17.5一起引入了一种现代化的方法读取并生成的代码初始化组件对于桌面应用程序进程外设计师.它通过使用.NET编译器站台–更好地了解作为Roslyn SDK–用于所有相关任务。Roslyn编译器是一组的开源编译器和代码分析API。NET语言。它允许开发人员使用C#和Visual Basic编写、分析和操作代码。净值使用现代语言特征。它还提供了丰富的诊断和代码重构,以提高代码质量和开发人员生产力。它是黄金标准和当前在C#和VB中生成代码的最佳实践。而且,因为它是用于编译和构建目的的相同工具在Visual Studio中为任何C#或Visual Basic项目生成代码结果完全符合当前的编码标准。

此外,由于Roslyn编译器提供了某些API,因此它不仅知道对的特定语句、命令或方法的语法,但也关于这个代码块的语义在WinForms设计时,WinForms设计器可以指出内部代码的潜在问题初始化组件比以前更早、更准确。所以,它不仅知道你什么时候拼写“Buttne”是错误的–它还知道定义了输入错误的变量的内部初始化组件将是未知符号,并且能够指向那就完了。

但还有一系列其他好处:

  • 以前,基于CodeModel的CodeDOM构建只能在UI线程。这不仅是一个阻塞操作,它无法利用现代多核处理器的全部潜力。使用Roslyn编译器,我们将能够通过使用并行化。
  • 最近引入的旧系统没有一个简单的解释方法语言特征。使用Roslyn,我们可以选择引入语言功能,如姓名生成更健壮的代码,尤其是对于数据约束目的。此外,它还为更复杂的代码开辟了道路的内部生成初始化组件这将有助于针对上生成的HighDPI场景优化和均衡代码生成具有不同HighDPI设置的机器。
  • Roslyn编译器支持以下方面.editorconfig(编辑器配置)配置,所以在中生成的代码初始化组件与你和你的团队正在通过custom.editorconfig强制执行您的编码标准定义。

总之,有几个基本的编码元素与以前不同。省略在C#或在Visual Basic中是这样的例子之一。以下屏幕截图显示了使用Roslyn为中的按钮生成代码初始化组件:

InitializeComponent与经典和基于Roslyn的新代码生成的差异截图

如果您对移动代码的技术背景感兴趣在WinForms设计器中生成到Roslyn或如何配置初始化组件使用.editorconfig生成代码,看看这个WinForms中的技术文章回购他更详细地指出了所有这些事情。

关于主题的反馈对我们来说非常重要,所以请让我们了解您对WinForms代码生成的想法评论。如果您对WinForms Designer有建议或认为您发现错误,请随时在WinForms Github软件回购.

快乐的设计和编码!

作者

克劳斯·洛夫曼
高级软件工程师

27评论

讨论结束。登录以编辑/删除现有评论。

最新
最新
受欢迎的
最老的
  • 劳伦特·布尔乔伊斯 ·已编辑

    Winforms当然还没有死。我仍然是它的忠实粉丝。通过只使用代码构建UI,可以使开发方式现代化。
    看看github上这个非常鼓舞人心的项目:
    WinFormMarkup(Windows窗体标记)
    由于采用了这种方式,我现在只有最少的代码来表示表单,并且只包含数据边界控件。

  • 理人霍华德

    看起来17.5 Winforms Designer现在不仅自动格式化设计器代码,还自动格式化我的附加代码。这对我来说是一个彻底的停止。我们如何关闭除设计器文件之外的所有文件的自动格式设置?

    • 克劳斯·洛夫曼Microsoft员工 作者

      WinForms Designer只能触摸代码隐藏(Designer)文件中的代码并对其进行美化/格式化。我们遇到了几个关键案例(主要是在VB领域),在这些案例中,它或多或少地完成了它应该完成的任务,而那些案例我们将以17.5的价格提供服务。我想更好地理解你的情况。可以联系(klaus dot loefflmannät microsoft dot com)或打开一个。。。

      阅读更多信息
  • 威尔·吴 ·已编辑

    “WinForms在Visual Studio 2022版本17.5中引入了一种现代化的方法,用于读取和生成WinForms进程外设计器的InitializeComponent代码。它通过使用.NET编译器平台的API(更好地称为Roslyn SDK)来完成所有相关任务。”

    也许这解释了7.5经常无法呈现设计视图的原因。。。有奇怪的视觉结果和/或没有错误消息,或奇怪的错误消息?

    我有。。。

    阅读更多信息
    • 克劳斯·洛夫曼Microsoft员工 作者

      我从2002年开始就在C#WinForms和VS中工作,但是,我一定是在另一个星球上,在那里作者在Designer.cs文件中所指的“代码”与XML/XAML一样胖/瘦,或者是序列化/呈现属性、属性、事件等的任何其他描述性“配方”。,接口的…就像事件绑定可以在XAML中完成一样,它是在Designer文件中完成的。

      无论如何:我们正在做的工作。。。

      阅读更多信息
    • Maximilien Noal公司

      只需使用AvaloniaUI即可。

      它没有这些问题。

  • Daite Dve公司

    对不起,没有领会到改进的所有“伟大之处”。我看到您只是去掉了不必要的“this”,最后开始使用名称空间而不是完整命名。都完了吗?!?!最丑陋的想法是什么——将形式的设计(!!!)保留在CODE中??即使200年了,这也太愚蠢了!
    设计就像XML、JSON之类的声明。为什么微软仍然为WinForms保留旧的垃圾代码?你必须至少转向XML!(比如。。。

    阅读更多信息
  • 亚历山大·沃辛格

    我注意到了一个小小的TipEx,它的C#代码有一个类名为“Form1”,Konstructor被称为“Form2”。
    这也应该是Form1

  • 迈克尔·温莎 ·已编辑

    很高兴看到WinForms前端正在进行更多的工作。

    我唯一的抱怨是设计时DPI处理得有多高。目前,我必须使VisualStudioDPI不知道,以便对我的窗体/控件进行任何编辑。“切换到100%”对我来说不太好,所以最终我必须禁用DPI感知。如果。。。

    阅读更多信息
  • 理查德莫斯

    我认为有一件事没有得到解决(如果我错过了,请道歉),那就是什么它所支持的WinForms的特色–它是全局的吗。NET Framework或。核心,还是仅与绑定。净5+?

    提到流程外设计器暗示这只是5+。

    谢谢;
    理查德莫斯

    • 克劳斯·洛夫曼Microsoft员工 作者

      我们也可以在的Out-Of-Proc Designer中解决这个问题。NET Framework,我们正致力于解决64位Visual Studio 2022和真正旧的WinForms应用程序中的问题,这些应用程序仍然依赖于32位(通常)基于COM的组件。但我们认为,生成的代码风格与in-roc和out-of-proc Designer之间的不匹配太大了,因此此功能可能只对未来的WinForms应用程序有意义。。。

      阅读更多信息
      • 保罗·福纳里

        我真的很想看看。NET框架,特别是使用NameOf生成的绑定代码。
        我们希望升级到。NET6,7,8+,但我们需要(并等待)新的OOP设计器来实现的功能对等。NET框架一。

  • 马克斯·穆斯特穆勒

    同时WPF团队:zzzZZZzzzz

    • 丹尼尔·休斯

      唉……虽然我很想看到WinForms的改进,但我也很想看到WPF的类似投资。我一直在说,但当微软展示出新的、闪亮的东西时,为什么有人会接受微软的新技术(即MAUI),他们会抛弃你。

      • 坦维尔·巴达尔

        /我的名字滴银光和WCF。

    • 保罗·平托

      它并没有那么糟糕,至少它有一个设计器、Blend支持、DirectX支持。NET和XAML,表单验证,而不是像WinUI那样的3000个错误和计数。

  • gf秒

    可以在SuspendLayout和ResumeLayout之间保留从InitializeComponent调用自定义方法的方法。
    因为有些winform控件不稳定。所以让编写代码来设计UI非常重要!
    设计师没有处理一切的灵活性。通常代码更容易控制。

    如果我实现了我的请求,WinForm将非常棒,因为可以在代码设计器中查看预览的同时编写UI代码。。。

    阅读更多信息
    • 克劳斯·勒菲尔曼Microsoft员工 作者

      我不完全清楚你的意思,也不知道你想做什么,但要对组件或控件进行更可控的初始化,可以使用ISupportInitialize。这用于具有依赖属性的组件,其中属性的写入顺序很重要。基本上,初始化开始和结束时都会通知您的控件。同时,对于所讨论的财产,您是。。。

      阅读更多信息
  • 爱迪生·恩里克·安德烈亚西

    感谢您的更新。看到WinForms的发展真是太好了!我想知道我应该在哪里报告有关这个问题的问题,例如,当我选择项目资源而不是本地资源(在VB中)时,我得到了错误的序列化(和编译器错误)。我也有兴趣使用我的技能来尝试弥补这类错误。

    • 梅里·麦高Microsoft员工

      为了补充克劳斯的评论,如果您通过Visual Studio提交反馈单,有时我们会获得更多的日志和诊断信息。也就是说,无论您选择哪种沟通方式,我们都非常乐意与您合作–我们很高兴收到反馈,以便我们能够更快地解决最紧迫的问题🙂.

      ~Merrie McGaw,WinForms工程团队负责人。

反馈