WPF·知识目录
一、程序
流程
创建程序
在Visual Studio中点创建新项目 → WPF应用(.NET Framework) → 框架.NET Framework 4.6.2
开发程序
使用NuGet引入MVVM库,及在必要的时候引入其它库。
在项目根目录下,添加各层的目录。
在正确的目录中,添加用户界面、视图模型、业务逻辑、业务数据模型,及工具类、自定义控件等代码。
编写、 调试 各层代码,实现功能,进行重构、测试、优化,做好版本管理。
发布程序
在Release模式下,点生成 → 重新生成解决方案,将bin/Release目录下的文件打成zip包即可。
这将打包成绿色版程序,你也可以选择 打包成安装程序 。
目录
重要文件或目录 | 说明 |
---|---|
App.xaml和App.xaml.cs | 项目入口 |
Properties目录 | 项目配置 |
Resources目录 | 资源文件 |
<以下是程序各层目录> | |
Views目录 | 视图层,包含各界面的.xaml 及 .cs文件 |
ViewModels目录 | 视图模型层 |
Services目录 | 业务逻辑层 |
Models目录 | 实体层 |
Helpers目录 | 工具类 |
UserControls或Components目录 | 自定义控件 |
<以下是程序相关文件> | |
解决方案名.sln | 解决方案文件 |
项目名.csproj | 项目文件 |
packages.config和packages目录 | NuGet依赖包 |
App.config | 程序配置文件 |
bin目录 | 编译输出文件 |
obj目录 | 中间输出文件 |
分层
视图层(View,即.xaml和.cs文件)是用户与其交互的界面,只负责显示,不处理业务逻辑。
视图模型层(ViewModel)和View绑定,是MVVM模式的核心。
ViewModel中的一些属性,持有实体(Model)对象,作为视图模型的状态。XAML中控件的特性与这些属性绑定。
ViewModel中的一些属性,持有命令(Command)对象,作为视图模型的行为。XAML中控件的命令与这些属性绑定。
ViewModel中持有命令的属性,使用ViewModel中的响应方法来实例化。响应方法中调用注入的Service对象的业务逻辑方法。
Service的业务逻辑方法中,包含读写数据源(数据库、Web API等)的代码。方法签名中使用Model类,ViewModel层从而可以界面无关地调用业务逻辑。
任何程序都要做到将用户的操作正确地反映到数据源的状态、及当前界面的状态中。在MVVM架构中,ViewModel对象的命令中包含了界面逻辑,可以通过修改界面的状态数据,达到更新界面的显示。Service对象的方法中包含了业务逻辑,ViewModel对象通过调用Service对象的方法,达到与数据源的状态的一致。
其他包,如Components、Converters、DTOs、Messages、ValidationRules、Helpers等包,均存放处理特定问题的代码,在架构层面没有太大的意义。
运行
程序启动: 执行App.xaml.cs的Application_Startup方法,并加载App.xaml中指定的窗口文件
窗口加载: 触发Initialized和Loaded事件
数据绑定: 视图模型的属性、命令与界面控件绑定
操作处理: 用户在界面上的操作,由视图模型代码处理,调用业务逻辑层代码,访问网络、文件等资源
程序关闭: 执行App.xaml.cs的Application_Exit方法
程序
Application类 由App.xaml和App.xaml.cs定义。
可以为程序的生命周期事件( Startup 、 Activated、Deactivated 、 Exit 等)指定处理方法。可以在Startup处理方法的 StartupEventArgs.Args属性 中获得命令行参数。
可以使用 Application.Current 获得Application对象。
程序中使用的图片等文件,可以编译成 资源文件 ,或复制成 内容文件 ,或作为 源站点文件 保存在程序外部。使用 PackURI 引用这些文件。
通过 本地化 可以让程序支持多种语言。
窗口
窗口 包括 标题 、 图标 、 位置 、 大小 、 状态 、 可否重设大小 、 是否显示边框 、 是否显示任务栏 等属性。
可以为窗口的 生命周期 事件指定回调方法。
使用Show方法打开窗口 , 使用Owner属性设置所有者窗口 。
使用ShowDialog方法打开对话框窗口 , 使用DialogResult属性返回对话框结果 。
通过Application的 MainWindow属性 和 Windows集合 全局地访问主窗口和全部窗口。
二、WPF
界面
用 XAML标记语言 定义界面,.xaml文件和.cs文件分别是界面类的外观代码和行为代码。
XAML将标签元素组织成 树 , 元素 对应于类的实例, 命名空间 对应于类的命名空间。
元素的 特性Attribute 对应于类的属性Property、或父元素定义的 附加属性 。其中 Name 特性对应于自动生成的字段, 事件 特性对应于手动定义的方法。特性的值总是纯字符串, {标记扩展} 语法和 类型转换器 让字符串有了更强的能力。
元素可以有子元素,子元素可以是 属性元素 或嵌套元素( 内容属性 或 集合属性 )。
布局
Grid :表格,定义 行和列 及其 尺寸 (支持 拖动 ),将子元素放到指定的单元格中,子元素可以 跨行(列) 。
StackPanel :单列(行),子元素在该方向上自适应,在另一个方向上默认被拉伸。
WrapPanel :换行(列),子元素在该方向上自适应,在另一个方向上以最高(宽)的元素为准拉伸。
DockPanel :将子元素停靠到指定的边,最后一个子元素默认填充剩余空间。
Canvas :将子元素放到指定的坐标。
控件
基本控件
文字块TextBlock 用于显示文本,支持换行或显示点点点,也能用 内联标签 定义局部样式。
标签Label 用于充当另一控件的文本标签。
图片Image 用于显示远程图片、资源图片、内容图片或本地图片,可以 旋转、转换、裁剪 或 拉伸 。
表单控件
文本框TextBox 支持换行、输入回车,能触发选中文本事件。
按钮Button 的内容可以是任何控件。
复选框CheckBox 支持三种状态。
单选框RadioButton 支持创建分组。
组合框ComboBox 可以绑定数据列表。
滑块Slider 可以拖动选择数值。
数据控件
ItemsControl 用于渲染列表。
ListBox 也用于渲染列表,其中的列表项可被选中。
DataGrid 用于显示表格,可以自动生成列或者 自定义列 ,可以显示 行详细信息 。
TreeView 用于显示树,使用 分层模板 渲染嵌套列表。
界面控件
菜单Menu 可以包含多层的菜单项。
上下文菜单ContextMenu 用于实现右键弹出菜单。
工具栏ToolBar 用于放置工具按钮。
状态栏StatusBar 用于显示程序的状态信息。
进度条ProgressBar 用于显示程序的进度信息。
对话控件
MessageBox 用于向用户显示消息。
OpenFileDialog 用于打开文件。
SaveFileDialog 用于保存文件。
自定义控件
控件模板 包含控件的 可视化树 的内容, 修改控件模板 能给原生控件定义全新的外观。使用 TemplateBinding 将控件的属性与模板内部元素的属性绑定,使用 ContentPresenter、ItemsPresenter 等占位标签在模板中显示控件的子元素,使用 视觉状态 定义控件在不同状态下的外观。
创建具有完全自定义功能的控件,需要继承正确的基类,并添加自定义的 依赖属性 和 路由事件 。继承 UserControl 的用户控件的界面在XAML中直接定义。继承 Control 的自定义控件的界面不包含固定的内容,使用控件的开发者可以为之自定义控件模板。继承 FrameworkElement 的控件可以对外观进行底层的精确控制。
样式
样式可以 定义在全局、窗口或控件 的 资源中 。如果 不指定Key而指定TargetType ,样式作用于资源范围内的全部这种控件。如果 指定Key ,样式作用于资源范围内明确使用此样式的控件。
样式可以有 触发器 子元素:属性触发器监视一个或 多个 控件的属性,数据触发器监视绑定的数据的属性,事件触发器监视事件的发生。触发器可以改变控件的外观,也可以启动 动画 。
绑定
依赖属性 基于其他值计算属性值。没有源头值时将使用 默认值 ,有多个源头值时使用 优先级 最高的值。
依赖属性可以用于 资源 、 样式 、 动画 、 数据绑定 。设置 验证回调 可以在给属性赋值前验证属性值是否合法,设置 更改回调 可以在属性值变化时发送通知,设置 强制回调 可在属性值不合法时将属性值改为合法的值,设置 可继承 让子元素能够继承父元素的属性值, 附加属性 让子元素能够拥有在父元素中定义的属性。
数据绑定 指把某个元素的某个 依赖属性 ,与某个对象的某个属性 绑定 ,使二者协同改变,减少显式为属性赋值的次数。绑定有单向、双向、单向到源等 模式 。
绑定时 使用Source或ElementName指定数据对象,使用RelativeSource指定相对于目标元素的对象 ,使用 DataContext 为子元素指定上下文。使用 Path 指定绑定到数据对象的属性路径。
当元素属性和对象属性的类型不同,用 值转换器 进行数据转换,简单的情况下用 StringFormat 即可。
使用 UpdateSourceTrigger 控制将数据对象属性修改后的值发送给元素属性的时机。
为了 将我们自定义的类用作数据源 ,将它实现INotifyPropertyChanged接口(这用于绑定单个对象,元素使用DataContext指定数据源),或 继承ObservableCollection类 (这用于 绑定集合对象 ,元素使用ItemsSource指定数据源,使用 数据模板 显示集合中的每一项)。
当使用 MVVM库 时,ModelView层继承 Observable基类 ,包含数据属性和用于控件绑定的 RelayCommand命令 ,不同组件使用事件总线进行 Messenger通信 ,不同层级的对象使用 IServiceProvider依赖注入 。
事件
路由事件 允许某个元素引发的事件被其祖先元素或子孙元素绑定的方法响应。
响应方法 的两个参数分别是引发该事件的sender对象和EventArgs对象。元素使用XAML上的事件属性、或代码中的+=运算符来绑定方法,使用-=运算符来解绑方法。
路由事件包括 直接、冒泡和隧道 (它与冒泡方向相反)路由事件。
按触发方式分为 生命周期事件 和 输入事件(鼠标事件、键盘事件等) 。
使用 命令 能将控件和逻辑解耦,简化多个控件对应同一逻辑的情况,并对控件的可用性做统一管理。
可以在 命令源控件 (菜单项、按钮等)上指定包含逻辑的 命令对象 、执行命令的 命令目标 和额外的 命令参数 。可以使用 命令绑定 将命令与逻辑连接起来。可以使用 内置命令 (如复制、粘贴)或 自定义命令 。
在MVVM框架中,命令被广泛用于将视图和模型解耦。
资源
资源 是某个范围(程序/窗口/控件)中的一组“名称-对象”对,通过名称可以在范围内重用该对象。
某个元素通过名称引用了一个对象后,当该名称改为对应于另一个对象时,如果是 静态资源 则该元素引用的对象不变, 动态资源 则该元素引用的对象改变。
可以{声明式地引用资源对象},也可以编程式地使用FindResource方法 查找资源对象 ,该方法会先在当前元素范围查找名称对应的资源对象,如果找不到,则向外查找。
可以 将资源写在单独的资源字典文件中,其他文件引入该文件 。
显示
可以用 画刷 绘制元素的前景、背景、边框,和形状的笔画、填充。画刷有 纯色 、 渐变 等种类,可以设置 不透明度 。
可以对元素运用 变换 ,包括 平移 、 旋转 、 缩放 、 扭曲 等。
可以轻松地绘制 形状 , 只需使用<形状元素>,设置位置、宽高和 笔画 、 填充 。形状包括简单图形( 直线 , 椭圆 , 矩形 , 折线 , 多边形 )和使用 路径 绘制的矢量图。路径使用 几何图形 描述复杂的几何信息。
可以用 Visual Layer 和 WriteableBitmap 进行底层的绘制,只有特殊的情况下需要这么做。
可以 构建3D场景 ,为此需要设置 视口 、 模型 、 摄像机 、 材质、纹理 、 光源 、 转换 、 动画 等。
动画
动画 的本质是在指定时间内,把 某个对象的某个依赖属性 ,从某个值变成某个值。
实例化动画对象,指定其 开始值、结束值 、 执行时间 ,及可选的 缓动函数 、是否 反向播放 和 重复 ,及动画执行结束后的 回调方法 。可以在代码中 编程式地定义动画 ,也可以在XAML中使用 故事板 声明式地定义动画。
可以使用 关键帧动画 对时间线进行更明确的控制,使用 路径动画 让元素沿着指定的轨迹移动。
动画常作用于画刷、变换、效果,也可以作用于任何依赖属性。
异步
可以创建和启动新的线程,在新线程中使用 Dispatcher 更新UI控件。
也可以 使用BackgroundWorker ,为其编写 启动任务 、 进度变化 、 任务完成 的回调方法,在后台执行任务。支持 取消正在执行的任务 。
也可以使用C#的 Task和async/await关键字 ,以近似于写同步代码的方式编写异步代码。
其他
可以使用 MediaPlayer类 或对应的 MediaElement控件 播放音频或视频。
参考
WPF入门 ,小而精
《WPF编程宝典》 ,大而全
WPF官方文档 ,大而乱
《深入浅出WPF》 ,小而美
三、C#
语法
每个变量都有一个静态类型 ,变量可以声明为 可空 。
内置类型 包括 整数 、 浮点数 、 布尔 、 字符串 等,此外还有 数组 、 集合 、 日期 等,可以进行 类型转换 。
运算符 包括 算数运算符 、 比较运算符 、 逻辑运算符 等,运算符可以 重载 。
表达式 是可以计算出一个值的语句, Lambda表达式 用于创建匿名函数。
使用 条件语句 、 循环语句 等 控制流语句 决定代码的执行顺序。
对象
类位于 命名空间 中,可以 继承 父类、实现 接口 ,类具有 多态 性。
属性
属性 是类的成员,是字段的封装,能像字段一样被轻松访问。
属性是用于访问私有字段的访问器方法,可以只提供读访问器get、写访问器set中的一个。
可以在最简单的情况下使用 自动实现的属性 。
可以 用set访问器在赋值之前进行验证 。
可以 将get访问器写成=>表达式 。
使用 索引器 能像访问数组一样使用下标访问对象。
方法
方法 是包含一系列语句的代码块。
方法中可以抛出 异常 。
可以使用 扩展方法 为现有类型添加方法。
委托
委托 是一种引用类型,引用具有特定参数列表和返回类型的方法。
可以 将委托实例与符合签名的方法关联 。可以使用委托名称(参数)调用方法。
委托包含方法的列表,可以使用+/-运算符调整该列表,实现 多播 。
事件
事件 使用发布-订阅模型,基于委托工作。
发布者定义事件 :事件被定义为发布者类中的一个委托类型的属性。委托类型可以使用EventHandler<T>泛型方式,可以接收事件参数。事件参数一般继承EventArgs类。
订阅者订阅事件 :订阅者定义一个符合委托类型的响应方法,使用+=运算符将它连接到发布者的事件上。也可以使用-=运算符取消订阅。
发布者触发事件:发布者在适当的时侯使用事件名称(参数)调用方法,订阅者定义的响应方法将被调用。
反射
可以使用 反射 查看类的元数据。
可以使用反射动态地实例化对象、调用方法,读写字段、属性的值。
泛型
可以使用 泛型 定义通用的功能类。
泛型能够将功能逻辑和业务逻辑解耦。
参考
C#教程 ,小而精
《C#入门经典》 ,大而全
四、.NET
文件
程序使用 流Stream 来读、写 字节。
程序 使用 Reader和Writer 来读、写字符 。
程序使用 异步方法 实现异步的读、写。
程序使用 File 、 Directory 、 FileInfo 、 DirectoryInfo 等类 管理文件和目录 ,使用Windows系统的 文件路径格式 。
程序使用 ZipFile 、 DeflateStream 、 GZipStream 等类来读、写压缩文件。
数据
程序使用 ADO.NET 管理各种数据源中的数据。
程序使用 Entity Framework 以ORM的方式管理数据库中的数据。
程序使用 LINQ 以类似于SQL的语法编写用于各种数据源(如集合、数据库、XML等)的 查询语句 。
程序使用 Cryptography 来 加密 、 解密 数据。
格式
程序使用 Regex 来用正则表达式处理文本。
程序使用 JsonSerializer 来序列化、反序列化JSON字符串。
程序使用XmlSerializer来 序列化 、 反序列化 XML字符串。
程序使用 IFormatter 来序列化、反序列化二进制流。
网络
程序使用 HttpClient 发送HTTP请求、获得HTTP响应。
程序使用 Socket 连接服务器。
线程
程序使用Thread等类 管理线程 。
异步
程序使用async关键字标记 异步 方法。
异步方法以表示任务的Task或Task<T>为名义返回值,如果使用后者,方法可以有类型为T的实际返回值。
只有在处理事件时,异步方法以void为返回值。
异步方法中可以使用await关键字暂停当前方法(但不会阻塞当前线程),等待Task完成。
工程
程序使用 垃圾回收器 自动管理内存。
程序 使用 NuGet 管理依赖库 。
程序使用 xUnit 进行单元测试。
参考
.NET文档 ,大而乱