我的 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. 应急响应靶机训练-Linux1

    靶机来源: 知攻善防实验室公众号 https://mp.weixin.qq.com/s/gCWGnBiwbqSnafXU1apJCA 我是在另一台主机上通过ssh连接到靶机进行解题的,以下为解题记录. ...

  2. ElasticSearch8 - SpringBoot整合ElasticSearch

    前言 springboot 整合 ES 有两种方案,ES 官方提供的 Elasticsearch Java API Client 和 spring 提供的 [Spring Data Elasticse ...

  3. KingbaseES 数据库CPU使用率过高问题与解决

    前言 本文介绍生产环境中CPU使用率高的常见原因,以及在CPU使用率高问题上的可能解决措施. 本文主要内容: 关于用于识别高CPU使用率的工具,例如kwr报告中DB CPU指标.kmonitor和sy ...

  4. linux系统执行 ifconfig命令ens33没有显示ip地址解决办法

    问题背景 安装虚拟机(以ubuntu为例)因为重启或更新等原因导致,无法通过ssh连接到虚拟机,本地cmd窗口ping虚拟机ip发现无法ping通 启动本地虚拟机 发现ens33 位置没有显示 ip地 ...

  5. pymysql连接、关闭、查询,python如何操作mysql数据库

    1 def get_conn(): 2 """ 3 :return: 连接,游标 4 """ 5 # 创建连接 6 conn = pymys ...

  6. Linux是什么与如何学习

    重点回顾 操作系统(Operation System) 主要在管理与驱动硬件,因此必须要能够管理内存.管理装置. 负责行程管理以及系统呼叫等等.因此,只要能够让硬件准备妥当(Ready)的情况, 就是 ...

  7. 论文阅读:A new approach solve the multi-product multi-period inventory lot sizing with supplier selection problem

    论文:A new approach solve the multi-product multi-period inventory lot sizing with supplier selection ...

  8. #树形dp#B 预算缩减

    题目 给定一棵树,你需要删去一些边(可以不删),使得剩下的图中每个点所在的连通块大小都\(\geq k\). 求删边的方案数,对\(786433\)取模.两种方案不同,当且仅当存在一条边在一个方案中被 ...

  9. Android NDK之使用 arm-v7a 汇编实现两数之和

    Android NDK之使用 arm-v7a 汇编实现两数之和 关键词: NDK armv7a WebRTC arm汇编 CMake 最近适配对讲程序,在webrtc的库编译的过程中,发现其为arm的 ...

  10. OpenHarmony 3.2 Beta多媒体系列——视频录制

    一.简介 媒体子系统为开发者提供了媒体相关的很多功能,本文针对其中的视频录制功能做个详细的介绍.首先,我将通过媒体子系统提供的视频录制Test代码作为切入点,给大家梳理一下整个录制的流程. 二.目录 ...