在实际的WPF开发中遇到很多再用Winform写法来写WPF的开发人员,很多时候项目进度延期、出现非必要的BUG等等、大多是因为开发人员虽然是再写WPF。

但是没有好好的学过WPF,就导致无法发挥出WPF的优势、很多地方都是开个线程处理完成后一个回调UI线程函数里面套一整段代码,这种情况下不仅难处理多线程问题、也会出现很多偶发性的BUG,不好追踪问题在哪里。同时也会因为开发人员对WPF的理解参差不齐导致架构设计和使用过程中代码凌乱。所以今天开始hello world 来梳理WPF。

我们通过hello world理解以下几个关键内容来整理XAML相关的知识点:

一、使用XAML创建可以显示hello world的文本框。

二、理解XAML中的文法规范级命名空间

三、XAML中的的属性和事件

四、从生成过程日志查看XAML的编译。

一、使用XAML创建可以显示hello world的文本框

  经常写winform窗体的同学一定深有感触、拿到UI给的图之后、我们如果想做的比较漂亮。大部分都是通过拖控件、然后把用户界面的后台代码中设置动画效果、大小、位置等等。如果需要适配多种分辨率是更难受的。特别是一些需要深度定制的东西、可能很多开发时间都会用在这里。解决一些稀奇古怪被测试出来的的显示问题。

  而在WPF中提出了XAML的概念、我们可以使用XAML标签来设计和构成我们的用户界面。而XAML丰富的标签一旦正确的使用,则会大大提高我们写出更漂亮的界面的能力。

只写文字大家都会反感。我们通过讲解例子来认识XAML。首先创建一个WPF工程。

1、写下第一行Hello world

打开VS选择创建WPF项目,点击下一步。

设置项目名称为Hello World点击创建。就创建了我们第一个WPF项目。

通过解决方案标签项我们可以看到整个解决方案的目录结构。而项目中的MainWindow就是我们本次分析的重点。

我们这次的重点在MainWindow.xaml和其对应的cs,所以其他部分不是本次的关注重点,也就不讲了。

首先双击MainWindow.xaml,在Grid标签中添加<TextBox Text="Hello world!"/>节点。然后在VS中按下F5键。程序就会执行编译,如果成功的话就会跑起来,并且看到我们输入的Hello world!。

<Window x:Class="HelloWorld.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:HelloWorld"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<TextBox Text="Hello world!"/>
</Grid>
</Window>

从我们看到这个显示出来的hello world!的这一刻开始,就正式开始了本章内容的讲解。

二、理解XAML中的文法规范级命名空间

 1 <Window x:Class="HelloWorld.MainWindow"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6 xmlns:local="clr-namespace:HelloWorld"
7 mc:Ignorable="d"
8 Title="MainWindow" Height="450" Width="800">
9 <Grid>
10 <TextBox Text="Hello world!"/>
11 </Grid>
12 </Window>

为了方便理解,我加入了行号,如果想系统的学习XAML可以先学习一下XML,XAML是遵循XML文法规范的,但是对于我们入门来说了解嵌套、 属性的赋值和设置,就可以了。

我们的整体XAML结构大致为

<Window>

  <Grid>

    <TextBox/>

  </Grid>

</Window>

我们当前的XAML根节点是一个Window节点,Window节点代表当前所显示的整个窗口、在Window节点内部有一个Grid节点,Grid节点是一个布局元素里面可以放置的所有的控件、Grid节点包含了一个内部的TextBox节点,而这个TextBox就是我们所说的控件,而我们看到的显示的内容是在Text=“”内赋值的。对于XAML中的内容。可以理解为把后台的.cs代码文件通过xaml可视化的方式进行设置,如果有不知道含义的地方,可以用鼠标点在对应的节点上然后按F12就可以跳转到对应的定义中。

比如我们把光标点在Grid上。按下F12。就会跳转到下图的位置。原来Grid继承自一个Panel。里面包含了Column、Row等等。我们就知道了。Grid是一个拥有横、列的网格面板。

而在TextBox上按F12之后,就会看到这是一个控件、显示或编辑文本的。

其他的元素同样的道理。把鼠标放置在对应的元素节点上按下F12就会显示对应的内容。

接下来我们来看命名空间。

名称空间看上去好像是一个URI的WEB位置,但实际上不是,URI格式的命名空间,不同组织就基本不会使用相同的名称空间创建不同的基于XAML的语言。

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 是WPF核心名称空间。 它包含了所有WPF类,包括创建界面的控件。
该名称空间没有使用前缀、所以它成为整个文档的默认命名空间。也就是说除非指明了名称空间,否则每个元素都直接使用这个名称空间。

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 是XAML名称空间,它包含各种XAML的特性,该命名空间被映射为前缀x。可以在元素名称之前放置x
来使用该名称空间。例如x:Name,x:Class="HelloWorld.MainWindow"。

xmlns:d="http://schemas.microsoft.com/expression/blend/2008"是旨在提供设计师支持,该名称空间使XAML元素上的这些属性仅影响XAML行为的设计方面。
而在运行过程中会忽略掉这些属性。比如d:DesignHeight="100" d:DesignWidth="100",这个在设计时看不到该控件时,在对应的控件上添加此属性特别有效。
在Blend下使用比较多的是针对集合的d:DataContext、d:DesignData。等等。感兴趣的可以看看Blend相关的。

xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 标识使运行时XAML解析器能够忽略设计属性,比如mc:Ignorable:d。d前缀的在运行时XAML解析器解析时就会忽略了。

xmlns:local="clr-namespace:HelloWorld" 这个就是我们工程自己的名称空间了。

x:Class="HelloWorld.MainWindow" x:Class特性是告诉XAML解析器用指定的名称生成一个新类,该类继承自XAML元素命名的类,也就是我们的根节点Window。

三、理解XAML中的的属性和事件

 XAML中的属性:

我们通过前面的讲解了通过跳转查看XAML节点的含义,比如<Grid>是布局用的Panel。<TextBox/>是显示和编辑无格式文本的。
那么现在我们来理解属性。
在元素中我们通过跳转了解到了XAML节点都是一个一个的类对象。里面定义了属性、方法及事件。那么在XAML中,我们可以在这里设置属性、事件。通过设置这些来修改样式及监听对应的事件消息。
那么在属性中分为简单属性和复杂属性。我们在Textbox上按F12跳转过去,然后我们找个属性来演示一下简单属性和复杂属性如何使用。

在Foreground上我们看到了该属性是一个Brush类型。而在WPF中Brush支持纯色、线性渐变色等等。我们设置代码如下。

这样我们就在第一个TextBox 上设置了背景色为一个枚举值。用于表示一个颜色值。 而当我们想设置复杂Brush的时候,我们就可以使用复杂属性,第二个TextBox通过属性的嵌套来创建一个复杂的线性画刷。2个TextBox显示效果如下:

但是新的问题又来了,现在大部分主流的App都支持更换皮肤,明暗主题什么的。而我们只能通过硬编码的形式设置属性,那岂不是要实现更换皮肤,每个控件都要设置一遍?

有没有什么办法能让XAML属性绑定一个变量,而我们去修改这个变量?

实现方法的办法之一就是使用扩展标记:假设我们的内容都放在一个windows里做演示:

添加window的资源。同时使用DynamicResource来绑定资源。就可以实现。一个资源修改,所有使用的地方都跟着变化。后面会详细讲到。如何使用扩展标记来进行主题切换。

而在WPF中提出的是依赖项属性的概念。这个和路由事件需要花费精力好好学一下。才能更好的使用和理解WPF。

XAML中的事件:

为了增强事件的传播能力,WPF中提出了路由事件的概念,路由事件可以在元素树中向上和向下传播,并且沿着传播路径被事件处理程序消费。我们在XAML中添加2个处理按下和抬起事件的代码。

后台的处理代码。

路由事件和依赖项属性这些主要会放在MVVM中讲。这里主要了解一下。XAML下如何创建事件处理程序。

四、从生成过程日志查看XAML的编译。

对于加载和编译XAML,有四种方式:

1、只使用代码来创建XAML对应的元素,类似于winform的写法;

2、使用代码和未经编译的XAML。

3、使用代码和编译过的XAML。

4、只使用XAML。

这里我们只去理解一个使用代码和编译过的XAML。其他的工作到目前未知,觉得用到的比较少,等真正用到了。只要理解了可以在去查如何使用。

当我们编译WPF程序时,编译过程分为了2个阶段,第一个个阶段是将XAML文件编译为BAML文件。我们使用的C#语言,所以会在临时文件生成对应的.g.cs文件

g代表generated。

当从XAML到BAML的编译结束后,编译器会编译代码和生成的部分类文件。编译过的代码会变成单个程序集。每个窗口的BAML都会作为独立资源被嵌入到程序集中。

我们通过修改VS的设置来查看编译过程。

在VS选择工具=>选项=>项目和解决方案=>生成并运行=>MSBuild项目生成输出详细程序=>设置为详细。而后点击编译。我们来观察输出的内容。

我们查看关键的几处

以上截图就是完整的编译过程。

我创建了一个C#相关的交流群。用于分享学习资料和讨论问题。欢迎有兴趣的小伙伴:QQ群:542633085

WPF教程一:创建Hello world来理解XAML的内容及编译的更多相关文章

  1. WPF教程一:基础

    一.WPF简介WPF:WPF即Windows Presentation Foundation,翻译为中文“Windows呈现基础”,是微软推出的基于Windows Vista的用户界面框架,属于.NE ...

  2. WPF 在一个dll创建一个Window(包含xaml),在另一个dll中再次继承 会出错

    https://social.msdn.microsoft.com/Forums/vstudio/en-US/e92390eb-bbfa-42fb-baa9-2286444c0dca/the-comp ...

  3. Quartz教程一:使用quartz

    原文链接 | 译文链接 | 翻译:nkcoder | 校对:方腾飞 本系列教程由quartz-2.2.x官方文档翻译.整理而来,希望给同样对quartz感兴趣的朋友一些参考和帮助,有任何不当或错误之处 ...

  4. CRL快速开发框架系列教程一(Code First数据表不需再关心)

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  5. NGUI系列教程一

    NGUI是Unity的一个插件,使用它来制作你的游戏UI必定将事半功倍.为什么这么说呢?首先我们说说GUI与NGUI的区别,GUI是Unity自带的绘制界面工具,它的成像原理是基于表层的,所以执行效率 ...

  6. Cobalt Strike使用教程一

    Cobalt Strike使用教程一     0x00 简介 Cobalt Strike是一款基于java的渗透测试神器,常被业界人称为CS神器.自3.0以后已经不在使用Metasploit框架而作为 ...

  7. 无废话SharePoint入门教程一[SharePoint概述]

    一.前言 听说SharePoint也有一段时间了,可一直处在门外.最近被调到SharePoint实施项目小组,就随着工作一起学习了一下实施与开发.但苦于网上SharePoint入门的东西实在太少,导致 ...

  8. 使用WPF教你一步一步实现连连看

    使用WPF教你一步一步实现连连看(一) 第一步: 问题,怎样动态的建立一个10*10的grid(布局) for (int i = 0; i < 10; i++){ RowDefinition r ...

  9. [转]无废话SharePoint入门教程一[SharePoint概述]

    本文转自:http://www.cnblogs.com/iamlilinfeng/p/3026332.html 一.前言 听说SharePoint也有一段时间了,可一直处在门外.最近被调到ShareP ...

随机推荐

  1. java 并发包JUC下的CountDownLatch和CyclicBarrier的理解和区别

    推荐这篇帖子,讲得不错~ https://blog.csdn.net/liangyihuai/article/details/83106584

  2. 最小生成树,Prim算法与Kruskal算法,408方向,思路与实现分析

    最小生成树,Prim算法与Kruskal算法,408方向,思路与实现分析 最小生成树,老生常谈了,生活中也总会有各种各样的问题,在这里,我来带你一起分析一下这个算法的思路与实现的方式吧~~ 在考研中呢 ...

  3. AutomicBoolean

    AutomicBoolean 介绍 java并发包下提供的原子变量,是原子类其中之一.基本特性是在多线程环境下,多个线程同时执行这些类的实例包含的方法时,具有排他性 当某个线程进入方法,不会被其他线程 ...

  4. YOLOv4没交棒,但YOLOv5来了!

    YOLOv4没交棒,但YOLOv5来了! 前言 4月24日,YOLOv4来了! 5月30日,"YOLOv5"来了! 这里的 "YOLOv5" 是带有引号的,因为 ...

  5. ARMed解决方案对DSP的战争

    ARMed解决方案对DSP的战争 ARM体系结构简化了数字信号处理 ARM与数字信号处理(DSP)有什么关系? ARM似乎在处理领域处于领先地位.该处理器已将其视为其最大的细分市场之一,这主要是由于该 ...

  6. VB 老旧版本维护系列---尴尬的webapi访问返回json对象

    尴尬的webapi访问返回json对象 首先Imports Newtonsoft.Json Imports MSXML2(Interop.MSXML2.dll) Dim URLEncode As Sy ...

  7. postman实现参数化执行及断言处理

    一.假设需要做的测试的参数如下: 注意保存为.csv文件时一定要选择格式为UTF-8 ,避免乱码. 二.输入参数和期望结果在postman中的用法: 注意一定要通过runner的方式进行运行,选择对应 ...

  8. 听说你还不知道Java代码是怎么运行的?

    作为一名Java程序员,我们需要知道Java代码是怎么运行的.最近复习了深入理解Java虚拟机这本书,做了一下笔记,希望对大家有帮助,如果有不正确的地方,欢迎提出,感激不尽. java 代码运行主要流 ...

  9. 解析 Nebula Graph 子图设计及实践

    本文首发于 Nebula Graph 公众号 NebulaGraphCommunity,Follow 看大厂图数据库技术实践. 前言 在先前的 Query Engine 源码解析中,我们介绍了 2.0 ...

  10. Java并发之ReentrantLock源码解析(三)

    ReentrantLock和BlockingQueue 首先,看到这个标题,不要怀疑自己进错文章,也不要怀疑笔者写错,哈哈.本章笔者会从BlockingQueue(阻塞队列)的角度,看看juc包下的阻 ...