很早就知道WPF这个东西,做项目中没用到,也就没去整理学习。作为winForm的升级版,未来windows桌面应用程序的趋势,有些公司招聘需求中也会提到熟悉WPF,于是就整理学习了一下WPF。
主要参考《C#高级编程 第八版》中XAML、WPF相关章节;《深入浅出WPF》和以下技术博客。
WPF(Windows Presentation Foundation)是微软推出的基于Windows Vista的用户界面框架,属于.NET Framework 3.0的一部分。它提供了统一的编程模型、语言和框架,真正做到了分离界面设计人员(xaml)与开发人员(.cs)的工作;同时它提供了全新的多媒体交互用户图形界面。详细介绍
WPF与WinForm开发有什么区别
WPF之What & Why (源自《深入浅出WPF》)
1、圣殿骑士
· 1. WPF 基础到企业应用系列1——开篇有益
· 2. WPF 基础到企业应用系列2——WPF前世今生
· 3. WPF 基础到企业应用系列3——WPF开发漫谈
· 4. WPF 基础到企业应用系列4——WPF千年轮回
· 5. WPF 基础到企业应用系列5——WPF千年轮回 续前缘
· 6. WPF 基础到企业应用系列6——WPF布局全接触
· 7. WPF 基础到企业应用系列7——深入剖析依赖
· 8. WPF 基础到企业应用系列8——依赖属性之“风云再起”
2、DotNet菜园
WPF入门教程系列一——基础 WPF学习之X名称空间详解
WPF入门教程系列二——Application介绍
WPF入门教程系列三——Application介绍(续)
WPF与WinForm一样有一个 Application对象来进行一些全局的行为和操作,并且每个 Domain (应用程序域)中仅且只有一个 Application 实例存在。和 WinForm 不同的是WPF Application默认由两部分组成 : App.xaml 和 App.xaml.cs,这有点类似于 Asp.Net WebForm,将定义和行为代码相分离。
微软把WPF中经常使用的功能都封装在 Application 类中了。
WPF入门教程系列四——Dispatcher介绍System.Windows.Threading.Dispatcher (调度)提供用于管理线程工作项队列的服务。不管是WinForm应用程序还是WPF应用程序,实际上都是一个进程,一个进程可以包含多个线程,其中有一个是主线程,其余的是子线程。在WPF或WinForm应用程序中,主线程负责接收输入、处理事件、绘制屏幕等工作,为了使主线程及时响应,防止假死,在开发过程中对一些耗时的操作、消耗资源比较多的操作,都会去创建一个或多个子线程去完成操作,比如大数据量的循环操作、后台下载。这样一来,由于UI界面是主线程创建的,所以子线程不能直接更新由主线程维护的UI界面。
所有 WPF 应用程序启动时都会加载两个重要的线程:一个用于呈现用户界面,另一个用于管理用户界面。呈现线程是一个在后台运行的隐藏线程,因此您通常面对的唯一线程 就是 UI 线程。WPF 要求将其大多数对象与 UI 线程进行关联。这称之为线程关联,意味着要使用一个 WPF 对象,只能在创建它的线程上使用。在其他线程上使用它会导致引发运行时异常。 UI 线程的作用是用于接收输入、处理事件、绘制屏幕以及运行应用程序代码。
实例:如何正确从一个非 UI 线程中更新一个由UI线程创建的对象。Dispatcher提供了两个方法,Invoke(同步操作)和BeginInvoke(异步操作),
同步与异步的区别
在WPF中,所有的WPF对象都派生自DispatcherObject(表示与Dispatcher 关联的对象),DispatcherObject暴露了Dispatcher属性用来取得创建对象线程对应的Dispatcher。DispatcherObject对象只能被创建它的线程所访问,其他线程修改 DispatcherObject需要取得对应的Dispatcher,调用Invoke或者BeginInvoke来投入任务。Dispatcher的一些设计思路包括 Invoke和BeginInvoke等从WinForm时代就是一直存在的,只是使用了Dispatcher来封装这些线程级的操作。
WPF入门教程系列五——Window介绍
用户通过窗口与 WPF独立应用程序进行交互。 窗口的主要用途是承载可视化数据并使用户可以与数据进行交互的内容。
WPF入门教程系列六——布局之Canvas(一)
WPF入门教程系列七——布局之WrapPanel与StackPanel(二)
WPF入门教程系列八——布局之Grid与UniformGrid(三)
WPF入门教程系列九——布局之DockPanel与ViewBox(四)
WPF入门教程系列十——布局之Border与ViewBox(五)
WPF的布局控件都在System.Windows.Controls.Panel这个基类下面,
布局是一个递归系统,实现在屏幕上对控件进行大小调整、定位和绘制,然后进行呈现。
一个Panel 的呈现就是测量和排列子控件,然后在屏幕上绘制它们。所以在布局的过程中会经过一系列的计算,那么子控件越多,执行的计算次数就越多,则性能就会变差。如果不需要进行复杂的布局,则尽量少用复杂布局控件(如 Grid和自定义复杂的Panel);如果能简单布局实现就尽量使用构造相对简单的布局(如 Canvas、UniformGrid等),这种布局可带来更好的性能。 如果有可能,我们应尽量避免调用 UpdateLayout方法。
1、 Canvas是最基本的面板,只是一个存储控件的容器,它不会自动调整内部元素的排列及大小,它仅支持用显式坐标定位控件,它也允许指定相对任何角的坐标,而不仅仅是左上角。
Canvas的主要用途是用来画图。Canvas默认不会自动裁减超过自身范围的内容,即溢出的内容会显示在Canvas外面,这是因为默认 ClipToBounds=”False”;我们可以通过设置ClipToBounds=”True”来裁剪多出的内容。
2、WrapPanel布局面板将各个控件从左至右按照行或列的顺序罗列,当长度或高度不够是就会自动调整进行换行,后续排序按照从上至下或从右至左的顺序进行
3、StackPanel就是将控件按照行或列来顺序排列,但不会换行。通过设置面板的Orientation属性设置了两种排列方式:横排(Horizontal默认的)和竖排(Vertical)。纵向的StackPanel默认每个元素宽度与面板一样宽,反之横向亦然。如果包含的元素超过了面板空间,它只会截断多出的内容。
4、Grid顾名思义就是“网格”,它的子控件被放在一个一个实现定义好的小格子里面,整齐配列。 Grid和其他各个Panel比较起来,功能最多也最为复杂。要使用Grid,首先要向RowDefinitions和ColumnDefinitions属性中添加一定数量的RowDefinitions和 ColumnDefinitions元素,从而定义行数和列数。
而放置在Grid面板中的控件元素都必须显示采用附加属性语法定义其 放置所在的行和列,它们都是以0为基准的整型 值,如果没有显式设置任何行或列,Grid将会隐式地将控件加入在第0行第0列。
5、UniformGrid 就是Grid的简化版,每个单元格的大小相同,不需要定义行列集合。每个单元格始终具有相同的大小,每个单元格只能容纳一个控件,将自动按照定义在其内部的元素个数,自动创建行列,并通常保持相同的行列数。UniformGrid 中没有Row 和Column 附加属性,也没有空白单元格。
UniformGrid布局控件很少使用。
6、DockPanel定义一个区域,在此区域中,您可以使子元素通过描点的形式排列,这些对象位于 Children 属性中。停靠面板其实就是在WinForm类似于Dock属性的元 素。DockPanel会对每个子元素进行排序,并停靠在面板的一侧,多个停靠在同侧的元素则按顺序排序。
注意:屏幕上 DockPanel 的子元素的位置由相关子元素的 Dock 属性以及这些子元素在 DockPanel 下的相对顺序确定。因此,具有相同 Dock 属性值的一组子元素在屏幕上的位置可能不同,具体取决于这些子元素在 DockPanel 下的顺序。子元素的顺序会影响定位,因为 DockPanel 会按顺序迭代其子元素,并根据剩余空间来设置每个子元素的位置。
7、ViewBox这个控件通常和其他控件结合起来使用,是WPF中非常有用的控件。定义一个内容容器。ViewBox组件的作用是拉伸或延展位于其中的组件,以填满可用空间,使之有更好的布局及视觉效果。
一个 Viewbox中只能放一个控件。如果多添加了一个控件就会报错。
8、Border 是一个装饰的控件,此控件绘制边框及背景,在 Border 中只能有一个子控件,若要显示多个子控件,需要将一个附加的 Panel 控件放置在父 Border 中。然后可以将子控件放置在该 Panel控件中。
WPF入门教程系列十一——依赖属性(一)
依赖属性出现的目的是用来实现WPF中的样式、自动绑定及实现动画等特性。
依赖属性的出现是WPF这种特殊的呈现原理派生出来的,与.NET普通属性不同的是,依赖属性的值是依靠多个提供程序来判断的,并且其具有内建的传递变更通知的能力。依赖属性基本应用在了WPF的所有需要设置属性的元素。依赖属性根据多个提供对象来决定它的值 (可以是动画、父类元素、绑定、样式和模板等),同时这个值也能及时响应变化。
依赖属性就是可以自己没有值,并能够通过Binding从数据源获 取值(依赖在别人身上)的属性。拥有依赖属性的对象被称为“依赖对象”。依赖项属性的重点在于“依赖”二字,既然是依赖了,也就是说:依赖项属性的值的改变过程一定与其它对相关,不A依赖B就B依赖A,或者相互依赖。
WPF入门教程系列十二——依赖属性(二)
WPF入门教程系列十三——依赖属性(三)
WPF入门教程系列十四——依赖属性(四)
WPF入门教程系列十五——WPF中的数据绑定(一)
WPF的数据绑定跟Winform与ASP.NET中的数据绑定功能类似,但也有所不同,在 WPF中以通过后台代码绑定、前台XAML中进行绑定,或者两者组合的方式进行数据绑定。您可以绑定控件、公共属性、XML 或对象,WPF中的数据绑定跟WinForm与ASP.NET相比,更加快捷、灵活和简单。
WPF 中的数据绑定,必须要有绑定目标和要绑定的数据源。绑定目标可以是继承自 DependencyProperty的任何可访问的属性或控件,例如 TextBox 控件的 Text 属性。数据源可以是其他控件的属性,可以是对象实例、XAML 元素、ADO.NET Dataset、XML数据。
一般情况下,Binding源是逻辑层的对象,Binding目标是UI层的控件对象,这样,数据就会源源不断 通过Binding送达UI层,被UI层展现,也就完成了数据驱动UI的过程。
WPF入门教程系列十六——WPF中的数据绑定(二)
WPF入门教程系列十七——WPF中的数据绑定(三)
WPF入门教程系列十八——WPF中的数据绑定(四)