1、在xaml代码中,我们可以看到有一个
2、如何在启动程序时决定先显示哪个窗体呢?答案是Application类的StartupUri 属性;
3、如何在WPF应用程序中设计出不同风格的界面?
答案是,我们只需要将这些设计要素(资源)放在Application的Resources属性中即可;
4、App.xaml,这个非常关键,它就代表当前应用程序本身:
应用程序的App.xaml前端代码,StartupUri="MainWindow.xaml"表示本程序第一个启动的窗体是MainWindow
5、当我们启动WPF应用时,首先被执行的是OnStartup方法,其次是OnActivated方法,如果我们把当前应用最小化或切换到其它程序时,这时OnDeactivated会被执行,再切回来时再次执行OnActivated方法,最后,当我们关闭程序时,OnDeactivated会再次被执行,最后执行的是OnExit方法;
Application的生命周期:
OnStartup->OnActivated->OnDeactivated->OnExit
6、Window窗体的生命周期
SourceIntialized4 -> Activated -> Loaded -> ConentRendered -> Deactivated -> Closing -> Deavtivated -> Closed
7、在C#的世界里,除了object,没有人敢称终极父类,而在WPF的世界里,DispatcherObject坐上了头把交椅。这个类位于程序集:WindowsBase.dll中,根据微软官网资料显示,DispatcherObject继承于object,虽然它在WPF框架算是终极父类,但在整个.NET中来看,仍然只不过是千年老二
8、作为DispatcherObject类的成员Dispatcher(调度员)又提供了哪些功能?简单点说,它便是后台线程和前台线程的架海紫金梁,虽然所有的控件都必须在前台UI线程中创建,但是在开发过程中,难免需要在后台线程中去操作控件,于是Dispatcher调度员提供了Invoke和BeginInvoke两个方法,供我们可以安全的访问UI线程中的控件
9、事件驱动模式:在需要的时候主动去改变控件的值的开发模式
10、数据驱动模式?控件的属性不再被直接赋值,而是绑定了另一个”变量“,当这个”变量“发生改变时,控件的属性也会跟着改变,这样的属性也被称为依赖属性;
几乎WPF控件的所有属性都可以采用这种模式去更新属性的值,因为所有控件都继承了DependencyObject这个基类
11、protected internal 关键字组合是一种成员访问修饰符, 表示受保护的内部成员。
12、UIElement基类定义了大量的路由事件。关于这些事件的回调函数,即以On开头的方法成员,都被声明成了protected virtual,意思是他们都可以被重载,这使得我们在开发业务时更加方便
13、Visibility实际上是一个枚举,它包含3个值,分别是Visible、Hidden、Collapsed。其含义分别是显示、隐藏、彻底隐藏(不占布局位置);
14、UIElement基类为我们提供了一系列的鼠标、键盘和触摸事件,并提供了一些常用的依赖属性。它可以呈现继承它的所有控件,为控件布局时调整位置和大小,响应用户的输入,引发一系列的路由事件,并继承了IAnimatable动画接口,用于支持动画的某些方面。
15、组件的Tag属性:这个属性非常重要,它是object类型,意味着可以保存任意类型的对象值。它就像FrameworkElement类身上的一个小口袋,但确能容纳万物。我们通常会将一些与控件相关的数据临时存放在Tag属性中,当把控件作为参数传递时,小口袋里面的对象也随之传递过去了。
16、组件Style属性:获取或设置此元素呈现时所使用的样式。
与Style相关的还有一个属性,叫FocusVisualStyle,顾名思义,控件在获得焦点时的样式。
17、什么是资源?资源,也就是资源字典,也就是ResourceDictionary类,它提供一个哈希表/字典实现,其中包含组件所使用的 WPF 资源以及 WPF 应用程序的其他元素。我们可以把WPF的控件、窗体、Application应用所用到的一切资源都放在其中,将多个ResourceDictionary元素合并起来形成一个ResourceDictionary元素(ResourceDictionary也是一个隐式集合);
18、假定我们有一个View窗体,窗体有一个TextBox控件;又假如我们还有一个ViewModel实体,这个实体中有一个叫Name的属性。如果我们要将TextBox控件的Text属性和ViewModel实体的Name属性成功的建立绑定关系,必备的条件是什么?
View窗体继承于FrameworkElement类,所以每个窗体(或控件)都有一个叫DataContext的数据上下文属性。所以必备的条件是:ViewModel实体必须先赋值给View窗体的DataContext,ViewModel的Name属性才能绑定到TextBox控件的Text属性
19、Panel其实是一个抽象类,不可以实例化,WPF所有的布局控件都从Panel继承而来
Panel提供了GetZIndex和SetZIndex方法成员,分别表示获取某个元素的ZIndex顺序和设置某个元素的ZIndex顺序:
20、什么是ZIndex?这是Panel提供的一个附加属性。假如一个单行单列的Grid布局控件中有两个Button,正常情况下,这两个Button都会以撑满Grid的方式呈现在Grid中,那么,到底哪一个Button在上面,哪一个Button在下面呢?就看这两个Button的Panel.ZIndex附加属性的值,值越大越在上面,而值较小的那个Button将被上面的Button遮盖,从而在视觉上,用户只能看到一个Button。
21、有一个非常非常需要注意的事项,那就是Panel的Background属性。有时候我们希望在布局控件上实现鼠标点击事件的获取,请记得一定要给Background属性设置一个颜色值,如果不希望有具体的颜色,那就设置成Transparent 。不然,您会踩坑的!因为布局控件的Background属性没有值时,是不能引发鼠标相关事件的。
22、只要继承于UIElement的类(或控件),都可以添加到Panel或Panel子类的Children中,从而在前端呈现出来。
如果不需要进行复杂的布局,则尽量少用复杂布局控件(如 Grid和自定义复杂的Panel);如果能简单布局实现就尽量使用构造相对简单的布局(如 Canvas、UniformGrid等),这种布局可带来更好的性能。 如果有可能,我们应尽量避免调用 UpdateLayout方法。
23、Grid网格布局组件:
-Grid有两个非常关键的属性ColumnDefinitions和RowDefinitions,分别表示列的数量集合和行的数量集合
-默认的Gridr控件没有定义行数和列数,也就是说,Grid默认情况下,行数和列数都等于1,那么它就只有一个单元格
24、WrapPanel的子元素的高度和宽度都是根据子元素自身内容的尺寸呈现。另外,当WrapPanel处于水平排列时,子元素的HorizontalAlignment是不起作用的。
25、Control类虽然可以实例化,但是在界面上是不会有任何显示的。只有那些继承了Control的子类(控件)才会在界面上显示,而且所呈现的样子各不相同,为什么会是这样呢?
因为Control类提供了一个控件模板(ControlTemplate),而几乎所有的子类都对这个ControlTemplate进行了各自的实现,所以在呈现子类时,我们才会看到Button拥有Button的样子,TextBox拥有TextBox的样子
26、Control类还提供了两个事件,它们分别是PreviewMouseDoubleClick和MouseDoubleClick:
以Preview开头的事件叫隧道事件或预览事件,而MouseDoubleClick没有以Preview开头,所以它叫冒泡事件;
-WPF的前端代码其实是一棵树,当我们在某个目标控件上进行鼠标操作时,所引发的事件有两个方向,一是从Winow根节点一直路由到目标控件上,看起来就好像是从外面一直沿着这棵树路由引发至里面,这就像我们开车进入隧道一样,所以Preview开头的事件叫隧道事件。冒泡事件事件的路由方向相反,是从目标控件位置开始,一直路由引发至最外层的Window窗体
27、对于文本的显示,除了可以在Label中显示,我们还有一个控件也可以实现,那就是TextBlock文字块。而且,TextBlock控件直接从FrameworkElement基类继承而来,效率比Label标签更高
28、WPF几乎所有控件都可以拥有ToolTip小型提示弹窗!
29、打开一个外部网站:
Process.Start("http://www.wpfsoft.com");