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 框架構建相關,請看


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM