WPF 框架开发 ColumnDefinition 和 RowDefinition 的代码在哪

我的 VisualStudio 在更新到 2022 就构建不通过 WPF 仓库,提示我在 Grid 的代码里面找不到 ColumnDefinitionCollection 和 RowDefinitionCollection 等的定义,在我开始找 WPF 仓库关于这几个类型的定义时,居然找不到对应的源代码。本文来告诉大家在 WPF 仓库里面是如何存放几个类型

在上一篇博客 手把手教你如何构建 WPF 官方开源框架源代码 告诉大家如何进行本地构建,本文将此基础上继续进行解决在 VisualStudio 2022 预览版构建失败的坑,顺便告诉大家在 WPF 仓库里面那些有趣的代码存放方法

本文非新手友好,本文的 WPF 框架开发不是说开发一个基于 WPF 框架的应用,也不是指开发 WPF 应用。而是开发 WPF 这个框架,这是做底层开发的博客

以下是在 VisualStudio 2019 进行构建,十分简单,只需要部署环境完成之后进行构建即可

然而在 VisualStudio 2022 里面,将会在构建的时候提示失败

“f:\lindexi\Code\wpf\Microsoft.Dotnet.Wpf.sln”(默认目标) (1:2) ->
“f:\lindexi\Code\wpf\src\Microsoft.DotNet.Wpf\src\PresentationFramework\PresentationFramework.csproj”(默认目标) (11:28) ->
(CoreCompile 目标) ->
  f:\lindexi\Code\wpf\src\Microsoft.DotNet.Wpf\src\PresentationFramework\System\Windows\Controls\Grid.cs(309,16): error CS0246: 未能找到类型或命名空间名“ColumnDefinitionCollection”(是否缺少 using 指令或程序集引用?)
[f:\lindexi\Code\wpf\src\Microsoft.DotNet.Wpf\src\PresentationFramework\PresentationFramework.csproj]
  f:\lindexi\Code\wpf\src\Microsoft.DotNet.Wpf\src\PresentationFramework\System\Windows\Controls\Grid.cs(324,16): error CS0246: 未能找到类型或命名空间名“RowDefinitionCollection”(是否缺少 using 指令或程序集引用?) [f:\lindexi
\Code\wpf\src\Microsoft.DotNet.Wpf\src\PresentationFramework\PresentationFramework.csproj]
  f:\lindexi\Code\wpf\src\Microsoft.DotNet.Wpf\src\PresentationFramework\System\Windows\Controls\Grid.cs(3347,22): error CS0246: 未能找到类型或命名空间名“ColumnDefinitionCollection”(是否缺少 using 指令或程序集引用?)
 [f:\lindexi\Code\wpf\src\Microsoft.DotNet.Wpf\src\PresentationFramework\PresentationFramework.csproj]
  f:\lindexi\Code\wpf\src\Microsoft.DotNet.Wpf\src\PresentationFramework\System\Windows\Controls\Grid.cs(3348,22): error CS0246: 未能找到类型或命名空间名“RowDefinitionCollection”(是否缺少 using 指令或程序集引用?) [f
:\Code\wpf\src\Microsoft.DotNet.Wpf\src\PresentationFramework\PresentationFramework.csproj]
  f:\lindexi\Code\wpf\src\Microsoft.DotNet.Wpf\src\PresentationFramework\System\Windows\Controls\Grid.cs(4151,21): error CS0246: 未能找到类型或命名空间名“ColumnDefinitionCollection”(是否缺少 using 指令或程序集引用?)
 [f:\lindexi\Code\wpf\src\Microsoft.DotNet.Wpf\src\PresentationFramework\PresentationFramework.csproj]
  f:\lindexi\Code\wpf\src\Microsoft.DotNet.Wpf\src\PresentationFramework\System\Windows\Controls\Grid.cs(4152,21): error CS0246: 未能找到类型或命名空间名“RowDefinitionCollection”(是否缺少 using 指令或程序集引用?) [f
:\Code\wpf\src\Microsoft.DotNet.Wpf\src\PresentationFramework\PresentationFramework.csproj]

我进入了 WPF 仓库里面,想要看看 ColumnDefinitionCollection 和 RowDefinitionCollection 等的定义,但是在 VisualStudio 里面实际上是找不到这几个类的代码的

原因是在 WPF 中,上古的开发者觉得 RowDefinitionCollection 和 ColumnDefinitionCollection 的代码差不多,而 ColumnDefinition 和 RowDefinition 的代码也差不多,于是就想用黑科技,通过配置生成这些类型。可以在 WPF 仓库的 src\Microsoft.DotNet.Wpf\src\PresentationFramework\MS\Utility 文件夹看到很多有趣的逻辑,在此文件夹可以看到如下的几个文件

    ColumnDefinition.ti
    GridContentElementCollection.tb
    GridContentElementCollection.th
    RowDefinition.ti

打开 GridContentElementCollection.tb 文件,可以看到这里面的代码定义就特别有趣,以下是删减的部分

namespace System.Windows.Controls
{
    /// <summary>
    /// A <<collectiontype>> is an ordered, strongly typed, non-sparse 
    /// collection of <<itemtype>>s. 
    /// </itemtype></collectiontype></summary>
    /// <remarks>
    /// <<collectiontype>> provides public access for <<itemtype>>s 
    /// reading and manipulation. 
    /// </itemtype></collectiontype></remarks>
    public sealed class <<collectiontype>> : IList<<<itemtype>>> , IList
    {
        //------------------------------------------------------
        //
        //  Constructors
        //
        //------------------------------------------------------

        #region Constructors

        /// <summary>
        ///     Default ctor.
        /// </summary>
        internal <<collectiontype>>(<<ownertype>> owner)
        {
            _owner = owner;
            PrivateOnModified();
        }

        #endregion Constructors

    }

    /// <summary>
    ///     <<itemtype>> is a FrameworkContentElement used by Grid 
    ///     to hold column / row specific properties.
    /// </itemtype></summary>
    public class <<itemtype>> : DefinitionBase
    {
        //------------------------------------------------------
        //
        //  Constructors
        //
        //------------------------------------------------------

        #region Constructors

        /// <summary>
        ///     Default ctor.
        /// </summary>
        public <<itemtype>>()
            : base(DefinitionBase.ThisIs<<itemtype>>)
        {
        }

        #endregion Constructors

        //------------------------------------------------------
        //
        //  Public Properties
        //
        //------------------------------------------------------

        #region Public Properties 

        /// <summary>
        ///     Sets specified <<widthheight>> value for the <<itemtype>>.
        ///     Returns current <<widthheight>> value for the <<itemtype>>. 
        /// </itemtype></widthheight></itemtype></widthheight></summary>
        public GridLength <<widthheight>>
        {
            get { return (base.UserSizeValueCache); }
            set { SetValue(<<widthheight>>Property, value); }
        }

        /// <summary>
        ///     Sets specified Min<<widthheight>> value for the <<itemtype>>.
        ///     Returns current Min<<widthheight>> value for the <<itemtype>>.
        /// </itemtype></widthheight></itemtype></widthheight></summary>
        [TypeConverter(typeof(LengthConverter))]
        public double Min<<widthheight>>
        {
            get { return (base.UserMinSizeValueCache); }
            set { SetValue(Min<<widthheight>>Property, value); }
        }

        /// <summary>
        ///     Sets specified Max<<widthheight>> value for the <<itemtype>>.
        ///     Returns current Max<<widthheight>> value for the <<itemtype>>.
        /// </itemtype></widthheight></itemtype></widthheight></summary>
        [TypeConverter(typeof(LengthConverter))]
        public double Max<<widthheight>>
        {
            get { return (base.UserMaxSizeValueCache); }
            set { SetValue(Max<<widthheight>>Property, value); }
        }

        /// <summary>
        ///     Returns calculated device independent pixel value of <<widthheight>> for the <<itemtype>>.
        /// </itemtype></widthheight></summary>
        public double Actual<<widthheight>>
        {
            get
            {
                double value = 0.0;

                if (base.InParentLogicalTree)
                {
                    value = ((Grid)base.Parent).GetFinal<<itemtype>><<widthheight>>(base.Index);
                }

                return (value);
            }
        }
    }
}

可以看到,如果将上面代码的 <<collectiontype>> 等内容替换掉,那不就是实际上的类型定义了?实际上就是如此,还请打开一下 ColumnDefinition.tiRowDefinition.ti 文件看一下,以下是 ColumnDefinition.ti 文件的内容

::BEGIN_TEMPLATE
COLLECTIONTYPE:ColumnDefinitionCollection
ITEMTYPE:ColumnDefinition
OWNERTYPE:Grid
WIDTHHEIGHT:Width
::END_TEMPLATE

::END

从上面代码可以看到,从某个 <<foo>> 替换的规则也就可以猜到了。如将 <<collectiontype>> 根据 COLLECTIONTYPE:ColumnDefinitionCollection 的规则,替换为 ColumnDefinitionCollection 即可。同理替换其他的逻辑

其实在 WPF 里面,即使在 VisualStudio 2022 也是有自动生成的,不需要咱做什么科技

还请看看如下两个文件

f:\lindexi\Code\wpf\artifacts\obj\PresentationFramework\Debug\net6.0\ColumnDefinition.cs

f:\lindexi\Code\wpf\artifacts\obj\PresentationFramework\Debug\net6.0\RowDefinition.cs

那为什么我在本文开始依然构建失败呢?那就是需要问问神奇的 VisualStudio 2022 啦,因为在 VisualStudio 2022 预览版在生成了如上两个文件之前,就先跑去构建 Grid.cs 文件啦

那另一个问题是,是哪个逻辑负责生成以上的文件的?请打开 src\Microsoft.DotNet.Wpf\src\PresentationFramework\template.pl 文件,这是由古老的 perl 提供的黑科技。相信 Perl 只有上古的开发者才知道这是什么啦。本文不想去聊 Perl 的内容,原因是我也不知道,也不想去学

更多 WPF 框架构建相关,请看

posted @ 2021-08-19 08:45  lindexi  阅读(476)  评论(0编辑  收藏  举报