我的 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 框架构建相关,请看

WPF 框架开发 ColumnDefinition 和 RowDefinition 的代码在哪的更多相关文章

  1. WPF学习开发客户端软件-任务助手(下 2015年2月4日代码更新)

    时光如梭,距离第一次写的 WPF学习开发客户端软件-任务助手(已上传源码)  已有三个多月,期间我断断续续地对该项目做了优化.完善等等工作,现在重新向大家介绍一下,希望各位可以使用,本软件以实用性为主 ...

  2. [原创].NET 业务框架开发实战之九 Mapping属性原理和验证规则的实现策略

    原文:[原创].NET 业务框架开发实战之九 Mapping属性原理和验证规则的实现策略 .NET 业务框架开发实战之九 Mapping属性原理和验证规则的实现策略 前言:之前的讨论一直关注在怎么从D ...

  3. [原创].NET 业务框架开发实战之八 业务层Mapping的选择策略

    原文:[原创].NET 业务框架开发实战之八 业务层Mapping的选择策略 .NET 业务框架开发实战之八 业务层Mapping的选择策略 前言:在上一篇文章中提到了mapping,感觉很像在重新实 ...

  4. 【我们一起写框架】MVVM的WPF框架(五)—完结篇

    前言 这篇文章是WPF框架系列的最后一篇,在这里我想阐述一下我对框架设计的理解. 我对框架设计的理解是这样的: 框架设计不应该局限于任何一种设计模式,我们在设计框架时,应该将设计模式揉碎,再重组:这样 ...

  5. 【我们一起写框架】MVVM的WPF框架(一)—序篇

    前言 我想,有一部分程序员应该是在二三线城市的,虽然不知道占比,但想来应该不在少数. 我是这部分人群中的一份子. 我们这群人,面对的客户,大多是国内中小企业,或者政府的小部门.这类客户的特点是,资金有 ...

  6. 【我们一起写框架】MVVM的WPF框架(二)—绑定

    MVVM的特点之一是实现数据同步,即,前台页面修改了数据,后台的数据会同步更新. 上一篇我们已经一起编写了框架的基础结构,并且实现了ViewModel反向控制Xaml窗体. 那么现在就要开始实现数据同 ...

  7. 【我们一起写框架】MVVM的WPF框架(三)—数据控件

    这世上,没人能一次性写出完美无缺的框架:因为,任何一个框架都需要项目的淬炼,然后才能升华,趋近完美. 所以,框架是个反复修改的东西,最终形成的东西. 如果你学了一点技术,觉得自己可以写出框架了,觉得自 ...

  8. 【我们一起写框架】MVVM的WPF框架(四)—DataGrid

    前言 这个框架写到这里,应该有很多同学发现,框架很多地方的细节,其实是违背了MVVM的设计逻辑的. 没错,它的确是违背了. 但为什么明知道违背设计逻辑,还要这样编写框架呢? 那是因为,我们编写的是框架 ...

  9. Jquery如何序列化form表单数据为JSON对象 C# ADO.NET中设置Like模糊查询的参数 从客户端出现小于等于公式符号引发检测到有潜在危险的Request.Form 值 jquery调用iframe里面的方法 Js根据Ip地址自动判断是哪个城市 【我们一起写框架】MVVM的WPF框架(三)—数据控件 设计模式之简单工厂模式(C#语言描述)

    jquery提供的serialize方法能够实现. $("#searchForm").serialize();但是,观察输出的信息,发现serialize()方法做的是将表单中的数 ...

  10. 避免重复造轮子的UI自动化测试框架开发

    一懒起来就好久没更新文章了,其实懒也还是因为忙,今年上半年的加班赶上了去年一年的加班,加班不息啊,好了吐槽完就写写一直打算继续的自动化开发 目前各种UI测试框架层出不穷,但是万变不离其宗,驱动PC浏览 ...

随机推荐

  1. 《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南 - 第8章

    本章勘误: 暂无,等待细心的你告诉我哦. 本章注解: 暂无 本章释疑: 暂无,等待你的提问 致谢: MVP 林德熙 MVP 吕毅 sPhinX 相关链接 试读记录

  2. objective-c之Class底层结构探索

    isa 走位图 在讲 OC->Class 底层类结构之前,先看下下面这张图: 通过isa走位图 得出的结论是: 1,类,父类,元类都包含了 isa, superclass 2,对象isa指向类对 ...

  3. 【K8S】如何进入kubernetes的一个pod

    如何进入kubernetes的一个pod呢,其实和进入docker的一个容器相似: 进入docker容器 : docker exec -ti <your-container-name> / ...

  4. 手把手带你用香橙派AIpro开发AI推理应用

    本文分享自华为云社区<如何基于香橙派AIpro开发AI推理应用>,作者:昇腾CANN. 01 简介 香橙派AIpro开发板采用昇腾AI技术路线,接口丰富且具有强大的可扩展性,提供8/20T ...

  5. KingbaseES大数据量分区表添加主键与索引

    KingbaseES大数据量分区表添加主键与索引 一.环境信息: 系统信息: $ cat /etc/centos-release CentOS Linux release 8.2.2004 (Core ...

  6. 算法学习笔记【1】| LCA(最近公共祖先)

    LCA(最近公共祖先) Part 1:逐步上跳 假设u,v是所求的两点,先把深度大的点逐步上移直到深度相同. 然后两者同时上移,直到第一次遇到相同的点为止. 时间复杂度: O(n)<script ...

  7. python 国家标准行业编码标准格式化处理

    代码在上次的基础上做了一点优化,之前对项目要的最终结果理解有些偏差: 原始数据的那一列行业编码是存在三位数和四位数的,我上次理解的三位数就是分割成两位数进行查找,其实三位数的编码是由于第一位的0没有显 ...

  8. cloudflare认识2(picgo结合使用)

    参考:https://zhuanlan.zhihu.com/p/658058503 https://blog.csdn.net/CCCChris001122/article/details/13585 ...

  9. 标签栏切换效果 JS

    标签栏切换效果 JS 要求:class为tab-box的元素用于实现标签栏的外边框,,分别实现标签栏的标签部分和内容部分. html <div class="tab-box" ...

  10. MogDB SQLdiag 使用指南

    MogDB SQLdiag 使用指南 本文出处:https://www.modb.pro/db/411957 前提条件 需要保证用户提供训练数据. 如果用户通过提供的工具收集训练数据,则需要启用 WD ...