本文记录 WPF 在 dotnet 9 的一项 XAML 编写语法改进点,此改进点用于解决编写 Style 的 Setter 进行给 Value 赋值时,不能将 Value 当成默认内容,需要多写 Value 标签的问题。通过此改进点可减少两行 XAML 代码

更新: 由于此功能导致 BAML 内容变化,由高版本 SDK 构建将在低版本 Runtime 运行不起来。直接报错信息是 System.Windows.Markup.XamlParseException 异常,内部是 IndexOutOfRangeException: Index was outside the bounds of the array 异常。于是最终决定撤回更改


在原先的 WPF 版本里面,对 Style 的 Setter 填充复杂的对象内容时,大概的示例代码如下

<Style TargetType="Button">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                ...
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

可以看到 <Setter.Value> 属于不可省略的内容

在本次引入的改进之后,即可将 Setter 的 Value 当成默认内容,从而减少 <Setter.Value> 的代码,改进后的写法如下

<Style TargetType="Button">
    <Setter Property="Template">
        <ControlTemplate TargetType="Button">
            ...
        </ControlTemplate>
    </Setter>
</Style>

此改进是在许多年前,由 Thomas Levesque 大佬在 https://github.com/dotnet/wpf/issues/84 提出的。被微软的 Anjalihttps://github.com/dotnet/wpf/pull/8534 实现

此变更将影响 XAML 语法,对应的文档也进行了同步更新,详细请看 https://github.com/dotnet/dotnet-api-docs/pull/9581

为什么之前的版本里面,必须编写 <Setter.Value> 呢?这是因为在原先的版本里面 Style 的 Setter 的 Value 不是默认的内容,即在 Setter 标签里面直接放入内容,将不能被放入到 Value 属性里面

https://github.com/dotnet/wpf/pull/8534 的实现里面,将 Setter 的 Value 当成默认内容,于是在 Setter 里面放入的内容,将会自动给 Value 进行赋值

上述的核心逻辑在 src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/Baml2006/WpfGeneratedKnownTypes.cs 里面,给创建 Setter 时,配置 baml 类型里面内容对应的属性名是 “Value” 属性名,如以下代码

        private WpfKnownType Create_BamlType_Setter(bool isBamlType, bool useV3Rules)
        {
            var bamlType = new WpfKnownType(this, // SchemaContext
                                              556, "Setter",
                                              typeof(System.Windows.Setter),
                                              isBamlType, useV3Rules);
            bamlType.DefaultConstructor = delegate() { return new System.Windows.Setter(); };
            bamlType.ContentPropertyName = "Value"; // 这是本次更改的核心逻辑
            bamlType.Freeze();
            return bamlType;
        }

当前的 WPF 在 https://github.com/dotnet/wpf 完全开源,使用友好的 MIT 协议,意味着允许任何人任何组织和企业任意处置,包括使用,复制,修改,合并,发表,分发,再授权,或者销售。在仓库里面包含了完全的构建逻辑,只需要本地的网络足够好(因为需要下载一堆构建工具),即可进行本地构建


本文会经常更新,请阅读原文: https://blog.lindexi.com/post/dotnet-9-WPF-%E6%94%AF%E6%8C%81-Style-%E7%9A%84-Setter-%E5%A1%AB%E5%85%85%E5%86%85%E5%AE%B9%E6%97%B6%E5%8F%AF%E5%BF%BD%E7%95%A5-Value-%E6%A0%87%E7%AD%BE.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

如果你想持续阅读我的最新博客,请点击 RSS 订阅,推荐使用RSS Stalker订阅博客,或者收藏我的博客导航

知识共享许可协议 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接: https://blog.lindexi.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系

微软最具价值专家


无盈利,不卖课,做纯粹的技术博客

以下是广告时间

推荐关注 Edi.Wang 的公众号

欢迎进入 Eleven 老师组建的 .NET 社区

以上广告全是友情推广,无盈利