深入浅出WPF学习笔记
第一部分 深入浅出话XAML
第3章 系统学习XAML语法
3.2 XAML中为对象属性赋值的语法
3.2.4 标记扩展(Markup Extensions)
Text="{Binding ElementName=slider1,Path=Value,Mode=OneWay}"
这句就是标记扩展
- 当编译器看到这句代码时就会把花括号里的内容解析成相应的对象。
- 对象的数据类型名是紧邻左花括号的字符串。
- 对象的属性由一串以逗号连接的子字符串负责初始化(注意,属性值不再加引号)。
尽管标记扩展的语法简洁方便,但并不是所有对象都能用标记扩展的语法来书写,只有MarkupExtension类的派生类(直接或间接均可)才能使用标记扩展语法来创建对象。MarkupExtension的直接派生类并不多,它们是:

第5章 控件与布局
5.1 控件与布局
日常工作做打交道最多的控件无外乎6类
| 名称 | 解释 |
|---|---|
| 布局控件 | 可以容纳多个控件或嵌套其他布局控件,用于在UI上组织和排列控件。Grid、StackPanel、DockPanel等控件都属此类,它们拥有共同的父类 Panel。 |
| 内容控件 | 只能容纳一个其他控件或布局控件作为它的内容。Window、Button等控件属于此类,因为只能容纳一个控件作为其内容,所以经常需要借助布局控件来规划其内容。它们的共同父类是ContentControl。 |
| 带标题内容控件 | 相当于一个内容控件,但可以加一个标题(Header),标题部分亦可容纳一个控件或布局。GroupBox、TabItem等是这类控件的典型代表。它们的共同父类是HeaderedContentControl。 |
| 条目控件 | 可以显示一列数据,一般情况下这列数据的类型相同。此类控件包括ListBox、ComboBox等。它们的共同基类是ItemsControl。此类控件在显示集合类型数据方面功能非常强大。它们的共同父类是ItemsControl。 |
| 带标题条目控件 | 相当于一个条目控件加上一个标题显示区。TreeViewItem、Menultem都属于此类控件。这类控件往往用于显示层级关系数据,结点显示在其Header区域,子级结点则显示在其条目控件区域。此类控件的共同基类是HeaderedItemsControl. |
| 特殊内容控件 | 比如TextBox容纳的是字符串、TextBlock可以容纳可自由控制格式的文本、Image容纳图片类型数据……这类控件相对比较独立。 |
6类控件的派生关系如下图
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oYZymf4t-1639874773551)(C:/Users/gaoji/AppData/Roaming/Typora/typora-user-images/image-20211219084451897.png)]](https://javaforall.net/wp-content/uploads/2020/11/2020110817443450.jpg)
5.2 WPF的内容模型
5.3 各类内容模型详解
我们把符合某类内容模型的UI元素称为一个族,每个族用它们共同基类来命名。
5.3.1 ContentControl 族
特点如下:
- 均派生自ContentControl类
- 他们都是控件(Control)
- 内容属性的名称为Content
- 只能由单一元素充当其内容

5.3.2 HeaderedContentControl族
特点如下:
- 它们都派生自HeaderedContentControl类,
HeaderedContentControl是ContentControl类的派生类。 - 它们都是控件,用于显示带标题的数据。
- 除了用于显示主体内容的区域外,控件还具有一个显示标题(Header)的区域。
- 内容属性为Content和 Header 。
- 无论是 Content还是Header都只能容纳一个元素作为其内容。

5.3.3 ItemsControl族
特点如下:
- 均派生自ItemsControl类。
- 它们都是控件,用于显示列表化的数据。
- 内容属性为 Items或ItemsSource。
- 每种ItemsControl都对应有自己的条目容器( Item Container)。

5.3.4 HeaderedItemsControl族
特点如下:
- 均派生自HeaderedItemsControl类。
- 它们都是控件,用于显示列表化的数据,同时可以显示一个标题。
- 内容属性为Items、ItemsSource和 Header。
本组控件只有三个:MenuItem、TreeViewItem、ToolBar
5.3.5 Decorator族
- 均派生自Decorator类。
- 起UI装饰作用。
- 内容属性为Child。
- 只能由单一元素充当内容。

5.3.6 TextBlock和TextBox
这两个控件最主要的功能是显示文本。
- TextBlock 只能显示文本,不能编辑,所以又称静态文本。
- TextBox 则允许用户编辑其中的内容。TextBlock 虽然不能编辑内容,但可以使用丰富的印刷级的格式控制标记显示专业的排版效果。
- TextBox不需要太多的格式显示,所以它的内容是简单的字符串,内容属性为Text。
- TextBlock 由于需要操纵格式,所以内容属性是Inlines(印刷中的“行”),同时,TextBlock也保留一个名为Text的属性,当简单地显示一个字符串时,可以使用这个属性。
5.3.7 Shape族元素
- 均派生自Shape类。
- 用于2D图形绘制。
- 无内容属性。
- 使用Fill属性设置填充,使用Stroke属性设置边线。
5.3.8 Panel族元素
- 均派生自Panel抽象类。
- 主要功能是控制UI布局。
- 内容属性为Children。
- 内容可以是多个元素,Panel元素将控制它们的布局。

5.4 UI布局(Layout)
5.4.1 布局元素
5.4.2 Gird
- 可以定义任意数量的行和列,非常灵活。
- 行的高度和列的宽度可以使用绝对数值、相对比例或自动调整的方式进行精确设定,并可设置最大和最小值。
- 内部元素可以设置自己的所在的行和列,还可以设置自己纵向跨几行、横向跨几列。
- 可以设置Children元素的对齐方向。
基于这些特点,Grid适用的场合有:
- UI布局的大框架设计。
- 大量UI元素需要成行或者成列对齐的情况。
- UI整体尺寸改变时,元素需要保持固有的高度和宽度比例。
- UI后期可能有较大变更或扩展。
1. 定义Gird的行与列
2. 使用Gird进行布局
<Window x:Class="demo.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:demo" mc:Ignorable="d" Title="留言板" Height="240" Width="400" MinHeight="200" MinWidth="340" MaxHeight="400" MaxWidth="600"> <Grid Margin="10"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" MinWidth="120"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="80"/> <ColumnDefinition Width="4"/> <ColumnDefinition Width="80"/>
Grid.ColumnDefinitions> <Grid.RowDefinitions > <RowDefinition Height="25"/> <RowDefinition Height="4"/> <RowDefinition Height="*"/> <RowDefinition Height="4"/> <RowDefinition Height="25"/>
Grid.RowDefinitions> <TextBlock Text="请选择您的部门并留言:" Grid.Column="0" Grid.Row="0" VerticalAlignment="Center"/> <ComboBox Grid.Column="1" Grid.Row="0" Grid.ColumnSpan="4"/> <TextBox Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="5" BorderBrush="Black"/> <Button Content="提交" Grid.Column="2" Grid.Row="4" /> <Button Content="清除" Grid.Column="4" Grid.Row="4" />
Grid>
Window>
5.4.3 StackPanel
StackPanel可以把内部元素在纵向或横向上紧凑排列、形成栈式布局,通俗地讲就是把内部元素像垒积木一样“撂起来”。垒积木大家都玩过,当把排在前面的积木块抽掉之后排在它后面的元素会整体向前移动、补占原有元素的空间。基于这个特点,StackPanel适合的场合有:
- 同类元素需要紧凑排列(如制作菜单或者列表)。
- 移除其中的元素后能够自动补缺的布局或者动画。
StackPanel使用3个属性来控制内部元素的布局,它们是Orientation、HorizontalAlignment和VerticalAlignment,具体如表5-9所示。
<Window x:Class="demo.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:demo" mc:Ignorable="d" Title="选择题" Height="190" Width="300"> <Grid Margin="10"> <GroupBox Header="请选择没有错别字的成语" BorderBrush="Black" Margin="5"> <StackPanel Margin="5" > <CheckBox Content="A. 迫不及待"/> <CheckBox Content="B. 首屈一指"/> <CheckBox Content="C. 陈词滥调"/> <CheckBox Content="D. 唉声叹气"/> <CheckBox Content="E. 不可理喻"/> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right"> <Button Content="清空" Width="60" Margin="5"/> <Button Content="确定" Width="60" Margin="5"/> StackPanel> StackPanel> GroupBox> Grid> Window> 效果图:
5.4.4 Canvas
- 一经设计基本上不会再有改动的小型布局(如图标)。
- 艺术性比较强的布局。
- 需要大量使用横纵坐标进行绝对点定位的布局。
- 依赖于横纵坐标的动画
5.4.5 DockPanel
5.4.6 WrapPanel
WrapPanel内部采用的是流式布局。WrapPanel使用Orientation属性来控制流延伸的方向,使用HorizontalAlignment 和VerticalAlignment两个属性控制内部控件的对齐。在流延伸的方向上,WrapPanel会排列尽可能多的控件,排不下的控件将会新起一行或一列继续排列。
第二部分 游历WPF内部世界
第6章 深入浅出话Binding
6.2 Binding基础
public class Student: {
private string _name; public string Name {
get {
return _name; } set {
_name = value; } } }
实现接口的Student类:
public class Student:INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged; private string _name; public string Name {
get {
return _name; } set {
_name = value; //激发事件 if(this.PropertyChanged!=null) {
this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Name")); } } } }
经过这样一升级,当Name属性的值发生变化时 PropertyChanged事件就会被激发,Binding接收到这个事件后发现事件的消息告诉它是名为Name的属性发生了值的改变,于是就会通知Binding目标端的UI元素显示新的值。
public partial class MainWindow : Window {
Student stu; public MainWindow() {
InitializeComponent(); //准备数据源 stu = new Student(); //准备 Binding Binding binding = new Binding(); binding.Source = stu; binding.Path = new PropertyPath("Name"); //使用Binding连接数据源与Binding目标 BindingOperations.SetBinding(this.textBoxName, TextBox.TextProperty, binding); } private void Button_Click(object sender, RoutedEventArgs e) {
stu.Name += "Name"; } }
- 第一个参数用于指定 Binding的目标,本例中是this.textBoxName。
- 与数据源的Path原理类似,第二个参数用于为 Binding 指明把数据送达目标的哪个属性。只是你会发现在这里用的不是对象的属性而是类的一个静态只读( static readonly)的DependencyProperty类型成员变量!这就是我们后面要详细讲述的与Binding 息息相关的依赖属性。其实很好理解,这类属性的值可以通过 Binding 依赖在其他对象的属性值上,被其他对象的属性值所驱动。
- 第三个参数很明了,就是指定使用哪个Binding 实例将数据源与目标关联起来。

6.3 Binding的源与路径
6.3.1 把控件作为Binding源与Binding标记扩展
下面的代码是把一个TextBox 的 Text 属性关联在了Slider 的 Value属性上。
<Window x:Class="demo_02.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:demo_02" mc:Ignorable="d" Title="MainWindow" Height="110" Width="300"> <StackPanel> <TextBox x:Name="textBox1" Text="{Binding Path=Value, ElementName=slider1}" BorderBrush="Black" Margin="5"/> <Slider x:Name="slider1" Maximum="100" Minimum="0" Margin="5"/>
StackPanel>
Window>

6.3.2 控制Binding的方向及数据更新
6.3.3 Binding的路径(Path)
尽管在XAML代码中或者Binding类的构造器参数列表中我们以一个字符串来表示 Path,但Path 的实际类型是PropertyPath。下面让我们看看如何创建Path 来应对各种情况。
- 最简单的情况就是直接把 Binding 关联在 Binding源的属性上。语法如下:
等效的C#代码
Binding binding =new Binding({
Path=new PropertyPath("Value"), Source = this.sliderl}; this.textBox1.SetBinding(TextBox.TextProperty,binding);
或者使用Binding的构造器简写为:
Binding binding - new Binding("Value""){
Source = this.slider1}; this.textBox1.SetBinding(TextBox.TextProperty, binding);
- Binding还支持多级路径(通俗地讲就是一路“点”下去)。比如,如果我们想让一个 TextBox显示另外一个TextBox的文本长度,我们可以写:
<StackPanel> <TextBox x:Name="textBox1" BorderBrush="Black" Margin="5"/> <TextBox x:Name="textBox2" Text="{Binding Path=Text.Length, ElementName=textBox1, Mode=OneWay)" BorderBrush="Black" Margin="5"/>
StackPanel>
等效的C#代码
this.textBox2.SetBinding(TextBox.TextProperty, new Binding("Text.[3]"){
Source = this.textBoxl,ModeBindingMode.OneWay });
6.3.4 “没有Path”的Binding
Binding源本身就是数据且不需要Path来说明。典型的string、int,无法指出通过哪个属性来访问这个数据,只需要将Path的值设置为“.”或干脆不写(在XAML中可以),在C#中不能省略
6.3.5 为Binding指定源(Source)的几种方法
6.3.6 没有Source的Binding—使用DataContext作为Binding的源
6.3.7 使用集合对象作为列表控件的ItemsSource
附:常用的方法属性
| 名称 | 含义 |
|---|---|
| VerticalAlignment | 竖直对齐方式枚举类型 |
| HorizontalAlignment | 水平对齐方式枚举 |
| BorderBrush | 边框颜色枚举类型 |
| Visibility | 可见性枚举 |
| Opacity | 不透明度,接受数值在0.0到1.0间 |
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/203295.html原文链接:https://javaforall.net
