2.WPF中控件类之间的继承关系
在WPF中所有的控件都是继承DispatcherObject类,可以说在wpf中DispatcherObject是所有控件类的基类,而DispatcherObject却继承Object,而它所在的程序集是在WindowsBase.dll里。
看一张图,wpf控件继承关系图
1.Shape类
形状控件是WPF一大系列控件。WPF所有的形状控件都继承于Shape基类。Shape是一个抽象基类,它不能被实例化,所以我们在使用时只能实例化它的子类。而Shape的父类是FrameworkElement,所以,所有的Shape子类都是一个UIElement 类,因此形状对象可以用在面板和大多数控件中。
Path路径 | Path只有一个Data属性,这个属性的类型为Geometry。而Geometry又是一个抽象类,所以我们不能直接使用它,那它肯定会有一系列可以实例化的子类。没错,Geometry表示一个几何 |
Polygon多边形 | Polygon多边形,与Polyline类似,都有一个Points属性,只不过,Polygon会把起点和终点连接起来 |
Polyline折线 | Polyline表示由一系列线段组合绘制而成的折线,因为它有一个Points属性,用来保存这些点的坐标。这些坐标点用于绘制Polyline图形中各线段相接处的顶点。集合中第一个元素表示起点,最后一元素表示终点 |
Rectangle矩形 | Rectangle是一个比较简单而实用的图形控件,继承于Shape,有两个属性比较常用,即RadiusX和RadiusY,表示设置矩形的圆角。所以,通过这两个属性的设置,矩形也可以画出一个圆 |
Ellipse椭圆形 | Ellipse继承于Shape,Shape继承于FrameworkElement,所以,它可以设置其 Width 和 Height。 使用其 Fill 属性指定用于绘制椭圆形内部的 Brush。 使用其 Stroke 属性指定用于绘制椭圆形轮廓的 Brush。 StrokeThickness 属性指定椭圆形轮廓的粗细 |
Line线段 | Line(线段)继承于Shape,它自身只有4个属性,分别用于定义线段两端的端点坐标 |
2.Control类
Control是许多控件的基类。比如最常见的按钮(Button)、单选(RadioButton)、复选(CheckBox)、文本框(TextBox)、ListBox、DataGrid、日期控件等等。这些控件通常用于展示程序的数据或获取用户输入的数据,我们可以将这一类型的控件称为内容控件或数据控件,它们与前面的布局控件有一定的区别,布局控件更专注于界面,而内容控件更专注于数据(业务)。
Control类虽然可以实例化,但是在界面上是不会有任何显示的。只有那些继承了Control的子类(控件)才会在界面上显示,而且所呈现的样子各不相同,为什么会是这样呢?
因为Control类提供了一个控件模板(ControlTemplate),而几乎所有的子类都对这个ControlTemplate进行了各自的实现,所以在呈现子类时,我们才会看到Button拥有Button的样子,TextBox拥有TextBox的样子
3.ItemsControl类
ItemsControl 用于生成内容的集合,也就是说如果要显示大量的数据以列表的形式展示,那么可使用集合控件,集合控件都是继承ItemsControl 类
控件名 | 说明 |
ItemsControl | 集合控件的基类,本身也是一个可以实例化的控件 |
ListBox | 一个列表集合控件 |
ListView | 表示用于显示数据项列表的控件,它可以有列头标题 |
DataGrid | 表示可自定义的网格中显示数据的控件。 |
ComboBox | 表示带有下拉列表的选择控件,通过单击控件上的箭头可显示或隐藏下拉列表。 |
TabControl | 表示包含多个共享相同的空间在屏幕上的项的控件。 |
TreeView | 用树结构(其中的项可以展开和折叠)中显示分层数据的控件 |
Menu | 表示一个 Windows 菜单控件,该控件可用于按层次组织与命令和事件处理程序关联的元素。 |
ContextMenu | 表示使控件能够公开特定于控件的上下文的功能的弹出菜单。 |
StatusBar | 表示应用程序窗口中的水平栏中显示项和信息的控件。 |
4.ContentControl类
ContentControl是一个内容控件,它有一个Content属性,该属性的类型是object,它可以接收任意引用类型的实例。
控件名 | 说明 |
Button按钮 | Button因为继承了ButtonBase,而ButtonBase又继承了ContentControl,所以,Button可以通过设置Content属性来设置要显示的内容 |
ToggleButton基类 | ToggleButton为CheckBox(复选框)和RadioButton(单选框)的基类 |
CheckBox复选框 | CheckBox继承于ToggleButton,而ToggleButton才继承于ButtonBase基类 |
RadioButton单选框 | RadioButton也继承于ToggleButton,作用是单项选择,所以被称为单选框。本质上,它依然是一个按钮,一旦被选中,不会清除,除非它”旁边“的单选框被选中 |
RepeatButton重复按钮 | RepeatButton,顾名思义,重复执行的按钮。就是当按钮被按下时,所订阅的回调函数会不断被执行 |
Label标签 | Label控件继承于ContentControl控件,它是一个文本标签,如果您想修改它的标签内容,请设置Content属性 |
TextBlock文字块 | TextBlock是专业处理文本显示的控件,在功能上比Label更全面 |
TextBox文本框 | TextBox用来获取用户的键盘输入的信息,这也是一个常用的控件。它继承于TextBoxBase,而TextBoxBase又继承于Control |
RichTextBox富文本框 | RichTextBox继承于TextBoxBase基类,所以很大程度上与TextBox控件类似,两者在某些情况下可以互相替换。但是,如果要为用户提供更强大的文档编辑功能,非RichTextBox莫属 |
ToolTip控件(提示工具) | ToolTip控件继承于ContentControl,它不能有逻辑或视觉父级,意思是说,它不能单独存在于WPF的视觉树上(不能以控件的形式实例化),它必须依附于某个控件。因为它的功能被设计成提示信息,当鼠标移动到某个控件上方时,悬停一会儿,就会显示这个ToolTip的内容。 |
Popup弹出窗口 | Popup类似于ToolTip,在指定的元素或窗体中弹出一个具有任意内容的窗口。Popup继承于FrameworkElement,算得上是独门独户的控件,因为大多数控件都是从Shape、Control或Panel三个类继承而来 |
Image图像控件 | Image也算是独门独户的控件,因为它也是直接继承于FrameworkElement基类 |
GroupBox标题容器控件 | GroupBox控件的功能是提供一个带标题的内容容器,它继承于HeaderedContentControl类,HeaderedContentControl继承于ContentControl类。通常它用来做一些局部的布局 |
ScrollViewer控件 |
ScrollViewer控件封装了一个水平滚动条ScrollBar和一个垂直滚动条ScrollBar,ScrollViewer就是一个包含其它可视元素的可滚动区域控件。ScrollViewer继承于ContentControl,所以它也是一个内容控件,只能在Content属性中设置一个子元素,如果要在ScrollViewer中显示多个子元素,请设置一个集合控件。 |
ScrollBar滚动条 | ScrollBar表示一个滚动条,该滚动条具有一个滑动 Thumb,其位置对应于一个值。它继承于RangeBase抽象基类,RangeBase基类继承于Control基类。带滚动特质的还有两个控件,也继承于RangeBase抽象基类,它们分别是ProgressBar(进度条)和Slider(滑动条) |
Slider滑动条 | Slider滑动条与ScrollBar滚动条有点相似,甚至某些情况下,两者还可以互换使用。Slider也继承于RangeBase基类,其功能是提供一个可以滑动取值的控件。 |
ProgressBar进度条 | ProgressBar进度条通常在我们执行某个任务需要花费大量时间时使用,这时可以采用进度条显示任务或线程的执行进度,以便给用户良好的使用体验。 |
Calendar日历控件 | Calendar提供一个日历界面,供用户选择日期,它继承于Control基类 |
DatePicker日期控件 | DatePicker与Calender在某些属性上很相似,只是为了方便显示和操作,DatePicker将Calender进行了封装 |
Expander折叠控件 | Expander也是一个内容控件,它有一个标题属性和内容属性 |
MediaElement媒体播放器 | MediaElement,一个可以播放音频或视频的控件,继承于FrameworkElement基类 |
5.Panel类
Panel其实是一个抽象类,不可以实例化,WPF所有的布局控件都从Panel继承而来
控件名称 | 布局方式 |
Grid | 网格,根据自定义行和列来设置控件的布局 |
StackPanel | 栈式面板,包含的元素在竖直或水平方向排成一条直线 |
WrapPanel | 自动折行面板,包含的元素在排满一行后,自动换行 |
DockPanel | 泊靠式面板,内部的元素可以选择泊靠方向 |
UniformGrid | 网格,UniformGrid就是Grid的简化版,每个单元格的大小相同。 |
Canvas | 画布,内部元素根据像素为单位绝对坐标进行定位 |
Border | 装饰的控件,此控件用于绘制边框及背景,在Border中只能有一个子控件 |
6.FrameworkElement类(FrameworkElement 类 (System.Windows) | Microsoft Learn)
FrameworkElement类继承于UIElement类,继承关系是:Object->DispatcherObject->DependencyObject->Visual->UIElement->FrameworkElement,它也是WPF控件的众多父类中最核心的基类,从这里开始,继承树开始分支,分别是Shape图形类、Control控件类和Panel布局类三个方向。
FrameworkElement类本质上也是提供了一系列属性、方法和事件。同时又扩展 UIElement 并添加了以下功能:
7.UIElement类(UIElement 类 (System.Windows) | Microsoft Learn)
UIElement类继承了Visual类,在WPF框架中排行老四,它定义了大量的路由事件和大量的依赖属性。大部分输入和聚焦行为也在UIElement类中定义。 这包括键盘、鼠标和触笔输入的事件,以及相关的状态属性。 其中许多事件是路由事件,许多与输入相关的事件既具有浮升路由版本,也具有事件的隧道版本。
8.Visual类(Visual 类 (System.Windows.Media) | Microsoft Learn)
Visual类是WPF框架中第三个父类,主要是为 WPF 中的呈现提供支持,其中包括命中测试、坐标转换和边界框计算.
Button、TextBox、CheckBox、Gird、ListBox等所有控件都继承了Visual类,控件在绘制到界面的过程中,涉及到转换、裁剪、边框计算等功能,都是使用了Visual父类的功能
9.Dependency类(依赖属性概述 - WPF .NET | Microsoft Learn)
DependencyObject 类表示参与依赖属性系统的对象。属性系统的主要功能是计算属性的值,并提供有关已更改的值的系统通知。 参与属性系统的另一个类 DependencyProperty。 DependencyProperty 允许将依赖属性注册到属性系统,并提供有关每个依赖属性的标识和信息,而 DependencyObject 为基类,使对象能够使用此依赖属性。
INotifyPropertyChanged 类用于通知UI刷新,注重的仅仅是数据更新后的通知。DependencyObject 类用于给UI添加依赖和附加属性,注重数据与UI的关联。如果简单的数据通知,两者都可以实现的。
什么是数据驱动模式?控件的属性不再被直接赋值,而是绑定了另一个”变量“,当这个”变量“发生改变时,控件的属性也会跟着改变,这样的属性也被称为依赖属性
10.DispatcherObject类(DispatcherObject 类 (System.Windows.Threading) | Microsoft Learn)
在 WPF 中, DispatcherObject 只能由 Dispatcher 它与之关联的访问。 例如,后台线程无法更新与 Dispatcher UI 线程上关联的内容Button。 为了使后台线程访问该 Content 属性 Button,后台线程必须将工作委托给 Dispatcher 与 UI 线程关联的工作。 这是通过使用 Invoke 或BeginInvoke。 Invoke 是同步的, BeginInvoke 是异步的。 操作将添加到指定DispatcherPriority位置的队列Dispatcher中。
DispatcherObject 类的主要方针路线到底是什么呢?主要有两个职责:
1.提供对对象所关联的当前 Dispatcher 的访问权限,意思是说谁继承了它,谁就拥有了Dispatcher。
2.提供方法以检查 (CheckAccess) 和验证 (VerifyAccess) 某个线程是否有权访问对象(派生于 DispatcherObject)。CheckAccess 与 VerifyAccess 的区别在于 CheckAccess 返回一个布尔值,表示当前线程是否有可以使用的对象,而 VerifyAccess 则在线程无权访问对象的情况下引发异常。