能行 发表于 2023-6-15 20:53:06

【.NET 深呼吸】全代码编写WPF程序

学习 Code 总有这样一个过程:入门时候比较依赖设计器、标记语言等辅助工具;等到玩熟练了就会发现纯代码写 UI 其实更高效。而且,纯代码编写也是最灵活的。Windows Forms 项目是肯定可以全代码编写的,哪怕你使用了设计器,它最后也是生成代码文件;而 WPF 就值得探索一下了。咱们知道,WPF 使用 XAML 标记来构建 UI 部分。由于 XAML 扩展了许多功能,用起来自然比 HTML 舒服。但是,老周向来不喜欢标记语言,这也是我向来不喜欢搞前端的原因。尽管某些前端框架模仿 WPF 也搞出数据绑定、MVVM、数据模板之类的名堂,也很难说用得特舒服。
有很多中小型项目都会把 Web 前端部分外包出去,尤其是给私人做——比如一两个人或两三个人做,也不外给其他公司做。有些人总以为前端很火(这里头媒体造势的功劳不小),可往深层一挖,那可不一定了。Web 其实只做了一套 UI 罢了,后端许多是通用模型,既可以和 Web 前端对接,也可以和桌面前端对接,B/S、C/S 通杀的项目也不少。
很多行业软件,如工业医疗,甚至财务、进销存等,还是用成熟的技术好,尤其是桌面技术体验更佳。当然有些行业软件也有 Web UI,纯辅助,一般就是看看报表看看大图查查订单而已。生产力悠关的东西,你还得相信桌面的魅力,娱乐相关的就随便。当然也有用 Web 技术开发桌面UI的框架,这些东西能用但效果不算好,尤其是性能。老周这里说的性能只是要求较宽的性能,而不是苛刻要求下的性能。啥意思呢,就是说用 Web 技术做桌面程序,存在性能问题不需要专用工具测,肉眼就能感觉到严重的性能问题了——吃内存特大,占CPU有亿点高(虽说占得不算恐怖)。这里所说的性能问题要排除 VS Code,因为这货是个奇葩,性能表现挺好。
许多人容易被表面现象迷惑,比如认为招聘信息多的就以为很吃香。那可不一定,有些技术,招聘少并不代表用的人少。老在招聘的顶多说明这些岗位流动性大,这个公司的员工热爱跳槽罢了。近年来 Python 被“利益携带体”们炒得可热了,甚至一些新手以为 Python 是刚出来的新语言。你想多了,就算没有 C 语言早(1972),那也是 80 年代末的东东了。我在学 Python 的时候,估计某些小菜鸟还没出生呢。不要听那些培训班胡说八道,它们的目的是你的钱包,而不是你的码农生涯,它们说话从来不需要负责的。如果你除了 Python 什么都不会的话,那除了会写点“脚毛”外,你什么也干不成。不管你想玩人工智障、视觉神经还是别的东西,你得掌握C语言,特别是想搞更底层的。只会 Py 没准连工作都难找,更别说年薪 500W 越南币了。
在你不知道的领域,你可曾想象,VB6、易语言、Delphi、MFC 还有不少人在用呢。告诉你个秘密,学好汇编可能更吃香,以后会这个的人更少了。信不信由你。当然,积极学习新东西是没错的,这也老周一向主张。不过,你同时得清楚,许多技术之间并不存在相互替代的关系,只不过是你做什么样的程序,就用什么样的技术罢了。比如这桌面程序,你不用纠结,很简单:考虑跨平台的,首选 Qt;仅考虑 Windows 的,那多了去,随便,当然,微软自家自然是最合适的。
可是,一些脑子太灵活的人又纠结了,我选了 Qt,那我用 Widgets 做还是用 QML 做?我选了.NET,那我用 Windows Forms 还是 WPF?还是 MAUI ?对于这种问题,老周送你一句:“像你们这种人是没法改变的,只有滚出码农界”。
好了,上面扯了几段“废腑”之话,回归正题,咱们讨论 WPF,老周这里说的是完全用代码写,指的是一行 XAML 都没有。当然,大伙伴们肯定说那没问题的。构建常规界面绝对行得通,但遇到像数据模板、控件模板、资源字典这些,就得费一点点代码。虽然网上能找到几位同道中人写的小作文,但要么版本太旧,要么过于粗糙。于是老周逮住了这个机会,可以瞎扯蛋一回了。
前文多次强调,咱们就纯代码写 WPF 的,无一行 XAML。所以,默认的 WPF 项目模板咱们就不用了。咱们用控制台应用的模板就行了。来,动手练习一下。
首先,创建一个控制台项目。
dotnet new console -n MyApp -o .dotnet new 命令知道乎?嗯,用来创建项目的,然后是项目模板的名称,console 表示控制台应用程序。模板名字我记不住哟。记它干吗,执行一下下面这一句就能看各种模板了:
dotnet new list这里你可别理解歪了,它不是说用名叫 list 的模板创建项目啊,list 是列出可用的项目模板。然后,你能得到这个表:
模板名<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>   短名称<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>   语言<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>标记
----------------------------------------------------------------------------------------------------
ASP.NET Core gRPC 服务<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>   grpc<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> <NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Web/gRPC
ASP.NET Core Web API<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> webapi<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>   ,F#<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> Web/WebAPI
ASP.NET Core Web 应用<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>webapp,razor<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> <NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Web/MVC/Razor Pages
ASP.NET Core Web 应用(模型-视图-控制器)mvc<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>,F#<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> Web/MVC
ASP.NET Core 与 Angular<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>angular<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Web/MVC/SPA
ASP.NET Core 与 React.js<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> react<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Web/MVC/SPA
ASP.NET Core 空<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>web<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>,F#<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> Web/Empty
Blazor Server 应用<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>   blazorserver<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> <NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Web/Blazor
Blazor Server 应用空<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> blazorserver-empty   <NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Web/Blazor/Empty
Blazor WebAssembly 应用<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>blazorwasm<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>   <NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Web/Blazor/WebAssembly/PWA
Blazor WebAssembly 应用空<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>blazorwasm-empty<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> <NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Web/Blazor/WebAssembly/PWA/Empty
dotnet gitignore 文件<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>gitignore<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Config
Dotnet 本地工具清单文件<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>tool-manifest<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Config
EditorConfig 文件<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>editorconfig<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> Config
global.json file<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> globaljson<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>   Config
MSBuild Directory.Build.props 文件<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>   buildprops<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>   MSBuild/props
MSBuild Directory.Build.targets 文件<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> buildtargets<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> MSBuild/props
MSTest Test Project<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>mstest<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>   ,F#,VBTest/MSTest
MVC ViewImports<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>viewimports<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Web/ASP.NET
MVC ViewStart<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>viewstart<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Web/ASP.NET
NuGet 配置<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>   nugetconfig<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Config
NUnit 3 Test Item<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>nunit-test<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>   ,F#,VBTest/NUnit
NUnit 3 Test Project<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> nunit<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>,F#,VBTest/NUnit
Razor 类库<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>   razorclasslib<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Web/Razor/Library
Razor 组件<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>   razorcomponent<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>   <NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Web/ASP.NET
Razor 页面<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>   page<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> <NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Web/ASP.NET
Web 配置<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> webconfig<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Config
Windows 窗体应用<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> winforms<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> ,VB<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> Common/WinForms
Windows 窗体控件库<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>   winformscontrollib   ,VB<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> Common/WinForms
Windows 窗体类库<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> winformslib<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>,VB<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> Common/WinForms
WPF 应用程序<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> wpf<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>,VB<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> Common/WPF
WPF 用户控件库<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>   wpfusercontrollib<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>,VB<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> Common/WPF
WPF 类库<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> wpflib<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>   ,VB<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> Common/WPF
WPF 自定义控件库<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> wpfcustomcontrollib,VB<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> Common/WPF
xUnit Test Project<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>   xunit<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>,F#,VBTest/xUnit
协议缓冲区文件<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>   proto<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Web/gRPC
接口<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> interface<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>,VB<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> Common
控制台应用<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>   console<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>,F#,VBCommon/Console
枚举<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> enum<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> ,VB<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> Common
类<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>   class<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>,VB<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> Common
类库<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> classlib<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> ,F#,VBCommon/Library
结构<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> struct,structure<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> ,VB<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> Common
解决方案文件<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> sln,solution<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> Solution
记录<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> record<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>   <NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Common
辅助角色服务<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> worker<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>   ,F#<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope> Common/Worker/Web咱们平常用得多的都是前几那几个,比如 mvc、web、wpf、classlib 等。我们在命令中引用的就是项目模板的短名称即可。比如控制台就是 console。
-n 参数指定项目的名称,我这里是“MyApp”,-o 参数指定项目存放目录,“.” 表示当前目录。
接下来要改一下项目文件(*.csproj)。
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><OutputType>Exe</OutputType>
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><TargetFramework><em><strong>net7.0-windows</strong></em></TargetFramework>
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><ImplicitUsings>enable</ImplicitUsings>
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><Nullable>enable</Nullable>
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><UseWPF><strong><em>true</em></strong></UseWPF>
</PropertyGroup>

</Project>1、添加 MSBuild 属性 UseWPF,且设置为 true。有了这个你才能在项目中引用 WPF 有关的程序集。同理,如果要使用 Windows Forms,就将 UseWindowsForms 属性设置为 true。
2、TargetFramework 要在.NET版本后加上“-windows”,表示这是 Windows 平台特定的,Linux 上不可用的。类似的如 net7.0-android 等。
至于 OutputType 属性要不要改为 WinExe,.NET 5 以上是不需要的,它会自动判断启不启动控制台窗口。
好了,保存,关闭项目文件。可以写代码了。
在写代码前,咱们先理清楚一些核心对象的关系。你才会知道怎么写。Application 类是 WPF 程序启动的核心对象,通常表示该应用程序相关的初始化。所以,在 Main 方法中记得 new 一个。你可别太聪明,千万不要直接从 Application.Current 静态属性来获取。因为这时应用程序还没初始化呢,Current 属性还是 null。Current 属性适合在项目的其他代码中方便访问 Application 对象而使用的。
如果你没别的东西初始化,那就调用 Application 对象的 Run 方法。应用程序正式启动,并且主线程会卡在(也不是真的卡)这里,直到程序要退出了才从 Run 方法返回。其间,调度器会不断调度/处理各线程上的消息,直到消息循环终止。
窗口应用程序当然要一个主窗口。表示窗口的基类是 Window,可以直接用它,也可以派生出自己的类,然后初始化要在窗口上显示的控件。
public class MyWindow:Window
{
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>public MyWindow()
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>{
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>InitUI();
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>}

<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>private void InitUI()
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>{
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 本窗口的属性
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>this.Title = "鼠爷快乐园";
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>this.Height = 225;
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>this.Width = 315;
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 启动时窗口在屏幕中央
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>WindowStartupLocation = WindowStartupLocation.CenterScreen;
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 整点控件
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 两个block
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>TextBlock tb1 = new()
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>{
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Text = "每天毙一鼠",
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>TextAlignment = TextAlignment.Center,
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 文本颜色
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Foreground = new SolidColorBrush(Color.FromRgb(12, 50, 208))
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>};
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>TextBlock tb2 = new()
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>{
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Text = "添寿又增福",
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>TextAlignment = TextAlignment.Center
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>};
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 再加一个按钮
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Button btn = new()
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>{
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Content = "行动起来",
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Margin = new Thickness(0d, 15d, 0d, 2d)
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>};
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 单击事件
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>btn.Click += OnClick;
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 布局控件
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>StackPanel panel = new();
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 垂直方向
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>panel.Orientation = Orientation.Vertical;
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 添加子元素
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>panel.Children.Add(tb1);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>panel.Children.Add(tb2);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>panel.Children.Add(btn);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 作为窗口的内容
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>this.Content = panel;
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>}

<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>private void OnClick(object sender, RoutedEventArgs e)
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>{
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>MessageBox.Show("自在其间乐");
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>}
}Windows 属于内容控件,公开 Content 属性,用来设置单个对象引用。上述代码先创建两个 TextBlock 实例和一个 Button 实例,然后把它们塞进 StackPanel 中,再把 StackPanel 实例赋值给窗口的 Content 属性。
窗口类写好后,在 Main 方法中,调用 Run 方法时把窗口实例传进去。
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>static void Main(string[] args)
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>{
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Application app = new();
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>app.Run(new MyWindow());
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>}这个程序已经可以运行了。

 
************************************************************************************************
咱们继续探索。如果要用到数据绑定呢。在 XAML 中是用 {Binding} 扩展标记的,而在代码中对应的是 Binding 类,位于 System.Windows.Data 命名空间。
Binding 类的构造函数可以传递一个字符串常量,对应 {Binding Path=... } 中的 Path,即要绑定的对象路径。数据源则由 Source 属性设置。
public Binding(string path);关联绑定用的是 BindingOperations 类的静态方法 SetBinding,要获取已关联的 Binding 对象就调用 GetBinding 方法。
public static Binding GetBinding(DependencyObject target, DependencyProperty dp);
public static BindingExpressionBase SetBinding(DependencyObject target, DependencyProperty dp, BindingBase binding);BindingOperations 类本身是静态类,所以它的成员自然也是静态的。target 参数是绑定目标,即 WPF 对象,dp 是要绑定的依赖属性,binding 就是Binding对象。
咱们举个例子。
假设用以下类作为数据源。
public class Student
{
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>public int ID { get; set; }
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>public string? Name { get; set; }
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>public int Age { get; set; }
}窗口的结构:内容根为 Grid 对象,它包含三行两列,用来放六个 TextBlock 控件。
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Grid layout = new();
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 设置为窗口内容
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>this.Content = layout;
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 设置边距
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.Margin = new Thickness(13.5d);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 三行两列
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.ColumnDefinitions.Add(new ColumnDefinition()
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>{
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Width = GridLength.Auto
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>});
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.ColumnDefinitions.Add(new ColumnDefinition(){
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 星号,即 1*
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Width = new GridLength(1.0d, GridUnitType.Star)
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>});
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.RowDefinitions.Add(new()
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>{
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Height = GridLength.Auto
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>});
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.RowDefinitions.Add(new()
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>{
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Height = GridLength.Auto
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>});
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.RowDefinitions.Add(new()
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>{
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Height = GridLength.Auto
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>});ColumnDefinitions 用来定义列。上述代码中,第一列的宽度为 Auto,第二列的宽度为 *。
RowDefinitions 集合用来定义行。上述代码中,三行的高度都是 Auto。
然后 new 出六个 TextBlock,三个用来显示字段标签,三个用于数据绑定,显示属性值。
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 六个block
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>var tbIDf = new TextBlock(){
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Text = "学号:"
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>};
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>var tbNamef = new TextBlock()
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>{
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Text = "姓名:"
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>};
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>var tbAgef = new TextBlock()
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>{
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Text = "年龄:"
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>};

<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>TextBlock tbIDv = new();
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>var tbNamev = new TextBlock();
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>var tbAgev = new TextBlock();把六个 TextBlock 控件添加到 Grid 的子级中。
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.Children.Add(tbIDf);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.Children.Add(tbIDv);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.Children.Add(tbNamef);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.Children.Add(tbNamev);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.Children.Add(tbAgef);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.Children.Add(tbAgev);设置子元素所在行、列的 Grid.Row 和 Grid.Column 是附加属性,以 Grid.SetXXX 方法调用。
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.Children.Add(tbIDf);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.Children.Add(tbIDv);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.Children.Add(tbNamef);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.Children.Add(tbNamev);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.Children.Add(tbAgef);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.Children.Add(tbAgev);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// Row、Column 附加属性
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 第一行第一列
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Grid.SetRow(tbIDf, 0);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Grid.SetColumn(tbIDf, 0);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 第一行第二列
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Grid.SetRow(tbIDv, 0);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Grid.SetColumn(tbIDv, 1);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 第二行第一列
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Grid.SetRow(tbNamef, 1);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Grid.SetColumn(tbNamef, 0);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 第二行第二列
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Grid.SetRow(tbNamev, 1);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Grid.SetColumn(tbNamev, 1);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 第三行第一列
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Grid.SetRow(tbAgef, 2);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Grid.SetColumn(tbAgef,0);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 第三行第二列
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Grid.SetRow(tbAgev, 2);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Grid.SetColumn(tbAgev, 1);最后是创建三个 Binding ,为 Student 类的三个属性做绑定。
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>/* ID */
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Binding bindID = new(nameof(Student.ID))
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>{
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Source = this.stu
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>};
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>BindingOperations.SetBinding(tbIDv, TextBlock.TextProperty, bindID);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>/* Name */
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Binding bindName = new(nameof(Student.Name))
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>{
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Source = stu
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>};
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>BindingOperations.SetBinding(tbNamev, TextBlock.TextProperty,
bindName);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>/* Age */
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Binding bindAge = new(nameof(Student.Age))
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>{
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Source = stu
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>};
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>BindingOperations.SetBinding(tbAgev, TextBlock.TextProperty, bindAge);完整的初始化方法代码如下:
private void InitUI(){<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Title = "数据绑定";<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Width = 240;<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Height = 185;<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 创建Grid<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Grid layout = new();<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 设置为窗口内容<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>this.Content = layout;<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 设置边距<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.Margin = new Thickness(13.5d);<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 三行两列<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.ColumnDefinitions.Add(new ColumnDefinition()<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>{<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Width = GridLength.Auto<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>});<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.ColumnDefinitions.Add(new ColumnDefinition(){<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 星号,即 1*<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Width = new GridLength(1.0d, GridUnitType.Star)<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>});<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.RowDefinitions.Add(new()<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>{<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Height = GridLength.Auto<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>});<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.RowDefinitions.Add(new()<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>{<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Height = GridLength.Auto<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>});<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.RowDefinitions.Add(new()<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>{<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Height = GridLength.Auto<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>});<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 六个block<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>var tbIDf = new TextBlock(){<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Text = "学号:"<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>};<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>var tbNamef = new TextBlock()<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>{<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Text = "姓名:"<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>};<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>var tbAgef = new TextBlock()<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>{<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Text = "年龄:"<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>};<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>TextBlock tbIDv = new();<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>var tbNamev = new TextBlock();<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>var tbAgev = new TextBlock();<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 把六个block放到 grid 上<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.Children.Add(tbIDf);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.Children.Add(tbIDv);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.Children.Add(tbNamef);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.Children.Add(tbNamev);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.Children.Add(tbAgef);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>layout.Children.Add(tbAgev);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// Row、Column 附加属性
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 第一行第一列
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Grid.SetRow(tbIDf, 0);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Grid.SetColumn(tbIDf, 0);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 第一行第二列
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Grid.SetRow(tbIDv, 0);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Grid.SetColumn(tbIDv, 1);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 第二行第一列
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Grid.SetRow(tbNamef, 1);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Grid.SetColumn(tbNamef, 0);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 第二行第二列
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Grid.SetRow(tbNamev, 1);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Grid.SetColumn(tbNamev, 1);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 第三行第一列
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Grid.SetRow(tbAgef, 2);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Grid.SetColumn(tbAgef,0);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 第三行第二列
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Grid.SetRow(tbAgev, 2);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Grid.SetColumn(tbAgev, 1);<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 数据绑定<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>/* ID */
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Binding bindID = new(nameof(Student.ID))
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>{
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Source = this.stu
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>};
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>BindingOperations.SetBinding(tbIDv, TextBlock.TextProperty, bindID);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>/* Name */
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Binding bindName = new(nameof(Student.Name))
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>{
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Source = stu
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>};
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>BindingOperations.SetBinding(tbNamev, TextBlock.TextProperty,
bindName);
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>/* Age */
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Binding bindAge = new(nameof(Student.Age))
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>{
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Source = stu
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>};
<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>BindingOperations.SetBinding(tbAgev, TextBlock.TextProperty, bindAge);}运行效果如下:

 
这时候,估计你也想到了一件事—— WPF 元素之间的绑定咋弄?对应的 XAML 扩展标记 {Binding ElementName=..., Path=... }。这个用代码写起来也不难,Binding 类有 ElementName 属性,可以引用已命名的对象。但是,在代码里面,咱们是直接用变量名来引用对象的,并没有分配对象名称。虽然 FrameworkElement 类的子类都继承了 Name 属性,但,设置这个 Name 属性 Binding.ElementName 是找不到的,必须要在 NameScope 对象里注册到XAML名称空间后才能被 ElementName 引用。
NameScope 类其实是个 Key=String, Value = Object 的字典,维护当前名称空间范围内的对象列表。对应的是 XAML 中的 x:Name = ...。NameScope 类定义了 NameScope 附加属性,允许将 NameScope 实例设置到目标对象上。XAML 语法是<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>但我们在写 XAML 时是不需要,都是自动添加的,用 x:Name 就行了。
在代码中用 SetNameScope 方法设置。
 
看看下面的例子。
void InitUI(){<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Title = "元素之间绑定";<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 根据内容自动调整窗口大小<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>SizeToContent = SizeToContent.WidthAndHeight;<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>StackPanel panel = new(){<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Orientation = Orientation.Vertical,<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope><NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Margin = new Thickness(15.0d)<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>};<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>this.Content = panel;   // 布局<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 文本输入控件<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>TextBox txt = new TextBox();<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>txt.Margin = new Thickness(3.0d, 5.0d, 3.0d, 8.5d);<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 给它分配一个名字,绑定时用到<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>NameScope myScope = new();<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>NameScope.SetNameScope(this, myScope);<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>myScope.RegisterName("txtInput", txt);<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 文本块<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>TextBlock tb = new TextBlock();<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>tb.Margin = new Thickness(5.0d, 0d, 5.0d, 0d);<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 绑定<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>Binding bind = new();<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>bind.ElementName = "txtInput";<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>bind.Path = new PropertyPath(TextBox.TextProperty);<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>bind.Mode = BindingMode.OneWay;<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 在文本框更改时更新数据<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>bind.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>BindingOperations.SetBinding(tb, TextBlock.TextProperty, bind);<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>// 添加到布局<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>panel.Children.Add(txt);<NameScope.NameScope>
    <NameScope />
</NameScope.NameScope>panel.Children.Add(tb);}这个方法也是写在 Window 的派生类中,SizeToContent = SizeToContent.WidthAndHeight 表示本窗口的宽度和高度会根据它要显示的内容自动调整。
由于 TextBlock 控件的文本来源于 TextBox,因此,要为 TextBox 注册一个名字“txtInput”。由于 FrameworkElement 类有 RegisterName 方法,所以,注册名称的代码也可以这样写:
NameScope.SetNameScope(this, new NameScope());
this.RegisterName("txtInput", txt);设置 bind.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged 允许在输入的内容更改后就马上更新绑定数据,能做到实时显示输入的内容。
效果如下:

好了,今天咱们先说到这儿,剩下的如模板、样式、动画、3D 什么的,咱们下次再探讨。
 

来源:https://www.cnblogs.com/tcjiaan/archive/2023/06/15/17482371.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 【.NET 深呼吸】全代码编写WPF程序