WPF 深入浅出 第一部分
作者:互联网
WPF 深入浅出
目录1 XAML概览
1.1 什么是XAML?
XAML是 WPF 技术中专门用于设计UI的语言
1.2 XAML 的优点
-
XAML可以设计出专业的UI和动画 (好用)
-
XAML不需要专业的编程知识,他简单易懂,结构清晰 (易学)
-
XAML使设计师能直接参与软件开发,随时沟通,无需二次转换 (高效)
-
结构分离
2 从零起步认识XAML
2.1 新建WPF项目
创建一个WPF桌面应用程序 会自动生成一些列文件 如下:
-
Properties 分支:里面的主要内容是程序要用到的一些资源(如 图标,图片,静态的字符串) 和 配置信息
-
Reference 分支: 标记了当前这个项目需要引用那些其他项目 默认都是.NET Framework 中的类库
-
App.xaml 分支:程序的主体 ,大家都知道Window 系统里面,一个程序就是一个进程,Window还规定,一个GUI进程还需要有一个窗体(Window)作为"主窗体",App.xaml 文件的作用就是声明了程序的进程会是谁,同时指定了程序的主窗体是谁,在这个分支里面还有一个文件--App.xaml.cs 他是App.xaml的后台代码
-
MainWindow.xaml : 程序的主窗体
2.2 解析最简单的XAML代码
MainWindow.xaml 代码:
<Window x:Class="_001_xmal的认识.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:_001_xmal的认识"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800" AutomationProperties.Name="MyFirstWpfApplication">
<Grid>
</Grid>
</Window>
写法: XAML 是 XML派生的,很多概念都通用 如果使用一个标签声明一个元素
为了表示同类标签中的某个标签与众不同,可以给他的特征(Attribute)赋值, 为特征赋值如下:
- 非空标签:
Content - 空标签
在这里 有必要吧 Attribute 和 property 这两个词分辨一下 property 属于面向对象理论范畴 Attribute 是语言上的东西相关 ...
他的总体结构是
<Window>
<Grid>
</Grid>
</Window>
XAML是一种声明示语言,当你见到一个标签,就意味着声明了一个对象,对象之间的层级关系要么是并列,要么是包含
下面这些代码就是
<Window x:Class="_001_xmal的认识.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:_001_xmal的认识"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800" AutomationProperties.Name="MyFirstWpfApplication">
</Window>
其中 Height Width Title AutomationProperties.Name 就是与Window 对象的 Property 相对应的
xmlns 是 (XML Namespace
) 的缩写, 作用是定义名称空间, 好处是 不同类重名时可以加名称空间来区分 xmlns特征的语法格式如下:
xmlns:[:可选的映射前缀]="名称空间"
xmlns 后可以跟一个可选的映射前缀,之间用冒号隔开
如果没写映射前缀的话,那就意味着所有来自这个名称空间的标签 都不用加前缀,称为"默认名称空间"---- 默认名称空间只能有一个!!!! (应该使用 使用最频繁的标签命名空间作为默认命名空间)
上面例子中,
而第一行中的Class 特征则来自于第三行的x:前缀对应的名称空间
实验:我们把xmlns加个前缀n 然后添加标签
<n:Window x:Class="_001_xmal的认识.MainWindow"
xmlns:n="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:_001_xmal的认识"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800" n:AutomationProperties.Name="wqe" >
<n:Grid>
</n:Grid>
</n:Window>
重点: XAML 中引用外来程序集 和 c# 是不一样的 c# using就行 但是XAML需要添加到引用中,然后通过 xmlns:前缀="clr-namespace: 命名空间;assembly=xxx"
例如使用 button 类
<Window
xmlns:b="clr-namespace:System.Window.Controls;assembly=PresentationFramework">
</Window>
默认引进的名称空间: http://schemas.microsoft.com/winfx/2006/xaml/presentation
- System.Windows
- System.Automation
- System.Windows.Controls
- System.Windows.Controls.Primitives
- System.Windows.Data
- System.Windows.Documents
- System.Windows.Forms.Integration
- System.Windows.Ink
- System.Windows.Input
- System.Windows.Media
- System.Windows.Media.Animation
- System.Windows.Media.Effects
- System.Windows.Media.Imaging
- System.Windows.Media.Media3D
- System.Windows.Media.TextFormatting
- System.Windows.Navigation
- System.Windows.Shapes
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="_001_xmal的认识.MainWindow
上面的 xmlns 对应的名称空间 对应XAML语言解析处理相关的程序集
如果将 x:Class 改为其他类 或者 该XAML下同名.cs文件的 InitializeComponent() 注释 可能会出问题
但是App.xaml中 定义了 StartupUri="MainWindow.xaml" 他是在告诉编译器 吧MainWindow.xaml作为主窗体 ,只要能解析成一个窗体,那么程序就可以正常运行
如果注释 InitializeComponent() 修改 x:class="名称空间.其他类" 使用中间语言反编译器 可以看到 项目编译的程序集包含一个名为 其他类的类
重点: 这说明,x:Class 这个Attribute 的作用是当XAML 解析器 将包含他的标签解析成 c#类后,这个类的类名是啥
但是出现了一个问题 两个类重名了 注意看 partial 关键字 目的可以将 不同方法放到不同类中!将这个类一份为二 所以我们可以将 UI 和 逻辑分开
// 标注重点:
/*
1.标签的定义
空标签 和 非空标签 标签的Attribute 每一个标签代表一个对象
2.名称空间
xmlns="" 默认名称空间 只能有一个
xmlns:x= "" 映射前缀
xmlns:前缀="clr-namespace: 命名空间;assembly=xxx" 程序集的引入
http://schemas.microsoft.com/winfx/2006/xaml/presentation 默认名称空间
http://schemas.microsoft.com/winfx/2006/xaml XMAL的解析 以及 x:Class 的解释
partial 关键字
*/
3 系统学习 XAML语法
3.1 XAML 文档的树形结构
和 html 一样 是树形机构
3.2 XAML 中为对象属性赋值的语法
在编译过程中 XAML 会为每个标签创建一个与之对应的对象,对象创建出来之后需要对他的属性初始化之后才更有意义
XAML 中为对象属性赋值共有两种语法:
- 使用字符串简单赋值
- 使用属性元素 (Property Element) 进行复杂赋值
下面我们以一个
3.2.1 使用标签的 Attribute 为对象属性赋值
通过MSDN文档库可以查到,Rectangle.Fill 的类型是 Brush Brush是一个抽象类, 凡是以Brush为基类的类都可以为Fill进行赋值
Brush的派生类:
- SolidColorBrush: 单色画刷
- LinearGradientBrush: 线性渐变画刷
- RadialGradientBrush:经向渐变画刷
- ImageBrush:位图画刷
- DrawingBrush: 矢量图画刷
- VisualBrush: 可视元素画刷
<Grid VerticalAlignment="Center" HorizontalAlignment="Center">
<Rectangle x:Name="rectangle" Width="100" Height="100" Fill="Blue"/>
</Grid>
SolidColorBrush brush = new SolidColorBrush();
brush.Color = Colors.Orange;
this.rectangle.Fill = brush;
有个案例 我把XMAL改为c#了
// 渐变
LinearGradientBrush linearGradient = new LinearGradientBrush();
linearGradient.StartPoint = new Point(0, 1);
linearGradient.EndPoint = new Point(1, 1);
linearGradient.GradientStops.Add(new GradientStop(Colors.LightBlue, 0.2));
linearGradient.GradientStops.Add(new GradientStop(Colors.Blue, 0.7));
linearGradient.GradientStops.Add(new GradientStop(Colors.DarkBlue, 1.0));
this.rectangle.Fill = linearGradient;
<Grid VerticalAlignment="Center" HorizontalAlignment="Center">
<Rectangle x:Name="rectangle" Width="100" Height="100">
<Rectangle.Fill>
<LinearGradientBrush>
<LinearGradientBrush.StartPoint>
<Point X="0" Y="0"/>
</LinearGradientBrush.StartPoint>
<LinearGradientBrush.EndPoint>
<Point X="1" Y="1"/>
</LinearGradientBrush.EndPoint>
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Offset="0.2" Color="LightBlue"/>
<GradientStop Offset="0.7" Color="Blue"/>
<GradientStop Offset="1.2" Color="DarkBlue"/>
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
LinearGradientBrush 的 GradientStops属性是一个 GradientStop的集合(GradientStopCollection) 即一系列的矢量渐变填充点,在这填充点之间,系统会自动进行差值预算,计算过度的彩色 填充矢量渐变的方向是 StartPoint 和 endPoint 两个属性 都是 Point 类型
3.2.2 标记扩展
有时候你会发现 你想给某Attribute 赋值 都会创建一个新的对象 但是如果使用的对象一样 或 一个对象赋值给两个属性,还有的时候需要给属性赋值Null 怎么搞?
所谓标记扩展 ,实际上是一种特殊的Attribute = Value 语法,其特殊的地方在于Value字符串是有一对 花括号及其括起来的内容组成
<StackPanel Background="LightSlateGray">
<TextBox Text="{Binding ElementName=slider1,Path=Value,Mode=OneWay}" Margin="5"/>
<Slider x:Name="slider1" Margin="5"/>
</StackPanel>
其中 Text="{Binding ElemnetName=slider1,path=Value,Mode=OneWay}" 就是标记扩展了
我们分析下这句代码:
- 当编译器看到这句代码时就会把花括号里的内容解析成相应的对象
- 对象的数据类型是紧邻左花括号的字符串
- 对象的属性由一串以逗号连接的子字符串负责初始化
Binding binding = new Binding(){Source=slider1,Mode=BindingMode.OneWay}
下面使用属性标签替换标记扩展
<StackPanel Background="LightSlateGray">
<TextBox Margin="5">
<TextBox.Text>
<Binding ElementName="slider1" Path="Value" Mode="OneWay"/>
</TextBox.Text>
</TextBox>
<Slider x:Name="slider1" Margin="5"/>
</StackPanel>
不是所有类都能使用标记扩展 ,只有MarkupExtension的派生类可以使用 他的派生类不多:
- System.Window.ColorConvertedBitmapExtension
- System.Window.Data.BindingBase
- System.Window.Data.RelativeSource
- System.Window.DynamicResourceExtension
- System.Window.Markup.ArrayExtension
- System.Window.Markup.NullExtension
- System.Window.Markup.StaticExtension
- System.Window.Markup.Type.Extension
- System.Window.ResourceKey
- System.Window.StaticResourceExtension
- System.Window.TemplateBindingExtension
- System.Window.ThemeDictionaryExtension
注意:
标记扩展是可以嵌套的,例如 Text="{Binding Source={StaticResource myDataSource},Path=PersonName}" 是正确的语法
标记有简写语法 如: {Binding Value ...} === {Binding Path=Value}
标记扩展类的类名以 Extension 结尾 带有的可以省略不写 如: Text="{x:Static...}"
3.3 事件处理器与代码后置
XAML标签的 Attribute 对应着 Property 但是有些对应着 对象事件 Event
事件处理器
WPF支持在XAML里面为对象的事件指定处理器, 方法是使用事件处理器的函数名为对应的对象事件的Attribute进行赋值:
<ClassName EventName="EventHandlerName"></ClassName>
例如按钮:
<Button Content="事件" Click="Button_Click"/>
如果翻译成c#代码
Button btn = new Button();
btn.Click += Btn_Click;
代码后置的意思就是 逻辑和ui分开
补充:如果想在XAML中用c#代码 可以使用 x:Code 标签 但是 x:Code的内容一定要使用XML的<![CATA[....]]>
<Button Content="事件" Click="Button_Click"/>
<x:Code>
<![CDATA[
private void Button_Click(object sender,RoutedEventArgs e){
MessageBox.Show("asdfasdf");
}
]]>
</x:Code>
3.4 导入程序集和引用其中的名称空间
把类库引用到项目中是引用其中名称空间的物理基础,无论是c#还是XAML都是这样
一旦引入成功,就能使用其名称空间
架设我们使用类库程序集为 MyLibray.dll 其中包括 Common和 Controls两个名称空间 那么XAML中引用语法是:
xmlns:映射前缀="clr-namespace=:名称空间,assembly=类库名"
xmlns:Common="clr-namespace=:Common,assembly=MyLibray"
xmlns:Controls="clr-namespace=:Controls,assembly=MyLibray"
一旦引入成功 就可以使用其语法
<映射名:类名></映射名:类名>
<Common:MessagePanel/>
c# 也可以像xaml一样引用 using Cmn = Common;
3.5 XAML的注释
<!---->
/*
总结:
xaml 标签的两种给属性值的方式 一个是对象 一个是字符串 对象的时候需要在 父标签内容中写属性的标签
扩展标记 {}
事件 EventName="" 例如 click="函数名"
程序集的引用 xmlns:映射前缀="clr-namespace:名称空间,assembly=程序集" 前提先引入
xaml的注释 <!---->
*/
4 x名称空间的详解
x字符可以随便改,只是我们修改的名称罢了 ,x名称空间里的成员(如 x:Class x:Name) 是专门给xaml编译器看的,用来引导xaml编译器把xaml代码转换为CLR代码
4.1 x名称空间里都有什么
x包含的均匀解释XAML语言相关,所以可以称之为XAML名称空间
x里面的参数可以告诉 编译器 编译结果与那个c#类结合,访问级别等
- x:Array 扩展标签
- x:Class Attribute
- x:ClassModifier Attribute
- x:Code XAML指令元素 上面有写
<![CDATA][]>
- x:FiledModifier
- x:Key
- x:Name
- x:Null 标签扩展
- x:Shared
- x:Static 标签扩展
- x:Subclass
- x:Type 标签扩展
- x:TypeArguments
- x:Uid
- x:XData XAML指令元素
我们可以看到 分为三大类: Atterbute
标签扩展
XAML指令元素
下面我们分别说下他们
4.2 x名称空间中Attribute
4.2.1 x:Class
这个Atttribute的作用是告诉XAML编译器将XAML标签的编译结果与后台代码中指定类合并,使用注意事项:
- 必须在根节点
- 根节点要与x:Class 的值 保持一致!!!!!!!!!!
- x:Class 指向的类要加partial关键字
4.2.2 x:ClassModifier
这个Attribute的作用是告诉XAML编译由标签编译生成的类具有怎样的访问控制级别
注意:
- 这个标签必须要有x:Class Attribute
- x:ClassModifier 要与 x:Class指向的值访问权限一致
4.2.3 x:Name
x:Name的作用有两个:
- 告诉XAML编译器,当一个标签带有 x:Name 时 除了为这个标签生成对应的实例之外,还要为这个实例声明一个引用变量,变量名就是 x:Name
- 将XAML标签所对应对象的Name属性(如果有) 也设置为x:Name的值,并把这个值注册到UI树上,方便查找
当一个 标签有 Name(FrameworkElement)的时候 Name 和 x:Name 都是一样的
4.2.4 x:FieldModifier
用于改变 x:Name 对应的 访问级别
<StackPanel x:Name="stackPanel" x:FieldModifier="public" Background="LightSlateGray">
只能改变变量的访问级别,前提要有一个x:Name
4.2.5 x:Key
最自然的检索方式莫过于使用"Key-Value"对的形式了, 在XAML文件中,我们可以把很多需要多次使用的内容提取出来放在资源字典中(Resource Dictionary)里,需要这个资源的时候可以 用key提取出来
例如我们在资源字典添加一个字符串
<Window x:Class="_002_标记扩展.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:_002_标记扩展"
mc:Ignorable="d"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<sys:String x:Key="myString">
Hello WPF Resource!
</sys:String>
</Window.Resources>
<StackPanel x:Name="stackPanel" x:FieldModifier="public" Background="LightSlateGray">
<TextBlock Text="{StaticResource ResourceKey=myString}" Margin="5"/>
</StackPanel>
</Window>
c# 也能拿到资源
private void Button_Click(object sender, RoutedEventArgs e)
{
string str = this.FindResource("myString") as String;
this.button.Content = str;
}
4.2.6 x:Shared
当我们把某些对象当做资源放进去 取出来的时候是对象本身还是对象副本呢
- 需要与x:Key配合使用
- 如果x:Shared 为 true 那么取出来的都是同一个对象
- XAML会给资源隐藏添加x:Shared="true", 默认情况都是同一个对象
4.3 x名称空间中的标记扩展
4.3.1 x:Type
MyButton xaml
<Window x:Class="_002_标记扩展.MyWindow"
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:_002_标记扩展"
mc:Ignorable="d"
Title="MyWindow" Height="170" Width="200">
<StackPanel>
<TextBox Margin="5"/>
<TextBox Margin="5"/>
<TextBox Margin="5"/>
<Button Content="OK" Margin="5"/>
</StackPanel>
</Window>
MyWindow
public class MyButton:Button{
public Type userWindowType { get; set; }
protected override void OnClick()
{
base.OnClick();
Window win = Activator.CreateInstance(this.userWindowType) as Window;
win?.ShowDialog();
}
}
主窗口
<local:MyButton userWindowType="{x:Type TypeName=local:MyWindow}" Margin="5" Content="show2" Click="MyButton_Click"/>
x:Type
标记扩展具有与 C# 中的 typeof()
运算符或 Microsoft Visual Basic 中的 GetType
运算符类似的功能。
userWindowType 通过x:type 修改了 类型为 MyWindow 所以显示的也是MyWindow
然后点击click后处理代码 代码显示窗口... x:type 标记扩展获取数据类型
4.3.2 x:Null *
重点是 key的访问方式
在xaml中 用来表示空值的是x:Null
<Window x:Class="WpfApp1.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:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<Style x:Key="{x:Type Button}" TargetType="{x:Type Button}">
<Setter Property="Width" Value="60"/>
<Setter Property="Height" Value="36"/>
<Setter Property="Margin" Value="5"/>
</Style>
</Window.Resources>
<StackPanel>
<Button Content="OK"/>
<Button Content="OK"/>
<Button Content="OK"/>
<Button Content="OK" Style="{x:Null}"/>
</StackPanel>
</Window>
<Button>
<Button.Style>
<x:Null/>
</Button.Style>
</Button>
4.3.4 x:Array
如果想在XAML文档里声明一个包含数据的X:array实例,必须使用标签声明才能做到
x:Array的作用就是通过他的Items属性向使用者暴露一个类型已知的 ArrayList实例,ArrayList内成员类型由: x:Array 的type指明
在WPF中把包含数据的对象称为 Data Source 如果想把 x:Array 当做一个数据向一个ListBox提供数据
<Window x:Class="WpfApp1.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:sys="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<ListBox Margin="5" Height="300">
<ListBox.ItemsSource>
<x:Array Type="sys:String">
<sys:String>hello</sys:String>
<sys:String>hello</sys:String>
<sys:String>hello</sys:String>
<sys:String>hello</sys:String>
</x:Array>
</ListBox.ItemsSource>
</ListBox>
</StackPanel>
</Window>
4.3.5 x:Static
他的功能是在xaml文档中使用数据类型的static成员
4.4 XAML指令元素
- x:Code
- x:XData
有一个类叫做 xmlDataProvider实例
<Window.Resources>
<XmlDataProvider x:Key="InventoryData" XPath="?">
<x:XData>
<supermaket xmlns="">
<Fruits>
...
..
</Fruits>
</supermaket>
</x:XData>
</XmlDataProvider>
</Window.Resources>
5 控件与布局
5.1 控件
日常我们打交道最多的控件无外乎6类,即
- 布局控件 :可以容纳多个控件或嵌套其他布局控件,用于UI上组织和排列控件 Grid StackPanel DockPanel 都属于 他们都继承 Panel
- 内容控件: 只能容纳一个控件 或 布局控件作为内容,Window Button 等控件属于此类,他们共同的父类是 ContentControl
- 带标题内容控件: 相当于一个内容控件,但是可以加个标题 (Header),标题部分亦可容纳一个控件或布局. GroupBox TabItem 等这些都是,他们的父类是 HeaderedContentControl
- 条目控件: 可以显示一列数据,一般情况下这列数据的类型相同, ListBox ComboBox等,他们的共同基类是 ItemsControl
- 带标题条目控件: 相当一个条目控件上加了一个标题 TreeViewItem MenuItem 都属于此类控件,这个用于显示层级关系 节点显示在 Header区域 他们共同基类是: HeaderedItemsControl
- 特殊内容控件: 比如TextBox 容纳的是字符串,TextBlock 可以容纳可自由控制格式的文本,Image容纳图片类型数据, 这些控件比较独立 ...
5.2 WPF的内容模型
WPF UI元素可以分为: 11个
名称 | 注释 |
---|---|
ContentControl | 单一内容控件 |
HeaderedContentControl | 带标题的单一内容控件 |
ItemsControl | 以条目集合为内容的控件 |
HeaderedItemsControl | 带标题的以条目集合为内容的控件 |
Decorator | 控件装饰元素 |
Panel | 面板类元素 |
Adorner | 文字点缀元素 |
Flow Text | 流式文本元素 |
TextBox | 文本输入框 |
TextBlock | 静态文字 |
Shape | 图形元素 |
5.3 各类内容模型详解
我们把符合某内容模型的ui元素 称为一个族,每个族用他们共同基类来命名
5.3.1 ContentControl 族
本族元素的特点如下:
- 均派生自ContentControl
- 他们都是控件 Control
- 内容属性的名称为 content
- 只能由单一元素充其当内容
如何理解 只能由单一元素充其当内容 这句话? 就是内容只能有一个 ..... 但是内容也可以是控件...
ContentControl族控件包括
1 | 1 | 1 | 1 |
---|---|---|---|
Button | ButtonBase | CheckBox | ComboBox |
ContentControl | Frame | GridViewColumnHeader | GroupItem |
Label | ListBoxItem | ListViewItem | NavigationWindow |
RadioButton | RepeatButton | ScrollViewer | StatusBarItem |
ToggleButton | ToolTip | UserControl | Window |
5.3.2 HeaderedContentControl族
本族元素特点如下:
- 他们都派生自 HeaderedContentControl 类,HeaderedContentControl 是ContentControl的派生类
- 他们都是控件 用于显示带标题的数据
- 除了主区域,还有一个显示标题(Header) 的区域
- 内容属性为 Content 和 Header 都只能容纳一个元素..
Expander | GroupBox | HeaderedContentControl | TabItem |
---|
<GroupBox Margin="10" BorderBrush="Gray" Height="80" Width="200">
<GroupBox.Header>
<Image Source="C:\Users\DSF-LSJ\Pictures\logo.ico" Width="20" Height="20"/>
</GroupBox.Header>
<TextBlock TextWrapping="WrapWithOverflow" Margin="10" Text="床前明月光,疑是地上霜,举头望明月,低头思故乡"/>
</GroupBox>
5.3.3 ItemsControl族
本族元素特点如下:
- 都派生自 ItemsControl类
- 他们都是控件,用于显示列表化的数据
- 内容 属性为 Items 或 ItemsSource
- 每种ItemsControl 都对应有自己的条目容器 (Item Container)
1 | 1 | 1 | 1 |
---|---|---|---|
Menu | MenuBase | ContextMenu | ComboBox |
ItemsControl | ListBox | ListView | TabControl |
TreeView | Selector | StatusBar |
<ListBox Margin="5">
<CheckBox Content="Time"/>
<CheckBox Content="Time"/>
<CheckBox Content="Time"/>
</ListBox>
书70页有写 怎么获取ui树的
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
List<student> newList = new List<student>()
{
new student(){id=1,name="hello1"},
new student(){id=2,name="hello2"},
new student(){id=3,name="hello3"},
new student(){id=4,name="hello4"}
};
this.testListBox.DisplayMemberPath = "name";
this.testListBox.SelectedValuePath = "id";
this.testListBox.ItemsSource = newList;
}
}
public class student
{
public int id { get; set; }
public string name { get; set; }
}
<ListBox x:Name="testListBox"/>
DisplayMemberPath 告诉 listbox显示那条属性
SelectedValuePath listbox.SelectValue 的时候显示
理解了ListBox的自动包装机制后 我把全部ItemsControl 对应的Item Contatiner列在下面
ItemsControl名称 | 对应的 item Container |
---|---|
ComboBox | ComboBoxItem |
ContenxtMenu | MenuItem |
ListBox | ListBoxItem |
ListView | ListViewItem |
Menu | MenuItem |
StatusBar | StatusBarItem |
TabControl | TabItem |
TreeView | TreeViewItem |
5.3.4 HeaderedItemsControl 族
顾名思义,都有itemsControl的特性 但是还可以有标题
只是多个一个 Header属性
MenuItem | TreeViewItem | ToolBar |
---|---|---|
MenuItem | TreeViewItem | ToolBar |
5.3.5 Decorator 族
本族中的元素是在UI上起装饰效果,如 可以使用border元素为一些组织在一起的内容添加个边框,如果需要组织在一起的内容能够自由缩放,则可以使用ViewBox元素
- 均为Decorator类派生
- 起UI装饰效果
- 内容属性为Child
- 只能由单一元素充当内容
ButtonChrome | ClassicBorderDecorator | ListBoxChrome | SystemDropShadowChrome |
---|---|---|---|
Border | InkPresenter | BulletDecorator | ViewBox |
AdornerDecorator |
5.3.6 TextBlock 和 TextBox
TextBlock只能显示文本 不能编辑,所以叫做静态文本,
TextBox 允许用户编辑
5.3.7 Shape族元素
这类元素没有自己的内容,我们可以使用Fill属性为他们的填充效果,还可以使用Stroke 属性设置他们的边界线效果
- 均为 Shape类
- 用于2D图形绘制
- 无内容属性
- 使用Fill 属性设置填充 ,使用 Stroke设置边线
5.3.8 Panel族元素
- 均派生自Panel 类
- 主要功能就是控制UI布局
- 内容属性为Children
- 内容可以多个 Panel控制他们布局
Canvas | DockPanel | Grid | TabPanel |
---|---|---|---|
ToolBarOverflowPanel | StackPanel | ToolBarPanel | UniformGrid |
VirtualizingPanel | VirtualizingStackPanel | WrapPanel |
..
5.4 UI布局(Layout)
WPF布局元素有一下几个:
- Grid 网格,可以自定义行和列并通过行列的数据,行高列宽控制布局 类似 html的table
- StackPanel:栈式面板 可以排成水平或垂直的一条线 当移除一个元素后,后面的元素会自动向前填充空缺
- Canvas: 画布 内部元素可以使用像素为单位的绝对坐标进行定位
- DockPanel:泊靠式面板,内部元素可以选择泊靠方向
- WrapPanel: 自动折行面板, 内部在排满一行后就能自动换行,类似html的流式布局
5.4.2 Grid
- 可以自定义任意数量行和列
- 内部元素可以选择在什么位置
- 可以设置 children 元素的对齐方式
使用场合:
- UI布局的大框架设计
- 大量ui元素需要排成行或列的情况
- UI整体尺寸改变时,元素需要保持固有的高度和比例等
- UI后期可能有较大的变更和扩展
-
定义Grid的行与列
Grid 类具有 ColumnDefinitions 和 RowDefinitions 两个属性 他们分别是 ColumnDefinition 和 RowDefinition 的集合,表示了Grid定义了多少列和多少行
两行三列:
<Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> </Grid>
设置 行高 和 列宽
单位:
英文名称 中文名称 简写 换算 Pixel 像素 px 默认单位 图像基本单位 Inch 英寸 in 1inch = 96pixel Centimeter 厘米 cm 1cm=(96/2.54)pixel Point 点 pt 1pt=(96/72)pixel <Grid ShowGridLines="True"> <Grid.RowDefinitions> <RowDefinition Height="50px"/> <RowDefinition Height="50px"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="40"/> <ColumnDefinition Width="1in"/> <ColumnDefinition/> </Grid.ColumnDefinitions> </Grid>
他的值我们可以设置三类
- 绝对值 数值后面加单位
- 比例值 数值后面加*****号 (他会把所有值加起来当分母 , 然后当个值做分子)
- 自动类型 填写 Auto字符串
-
使用Grid进行布局
<Window x:Class="_005_布局.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:_005_布局" mc:Ignorable="d" Title="MainWindow" Height="400" Width="400" > <Grid ShowGridLines="False" 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.Row="0" Grid.Column="1" Grid.ColumnSpan="4"/> <TextBox Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="5" BorderBrush="Black"/> <Button Content="提交" Grid.Row="4" Grid.Column="2"/> <Button Content="取消" Grid.Row="4" Grid.Column="4"/> </Grid> </Window>
5.4.3 StackPanel
- 同类元素需要紧凑排列(如制作菜单或者列表)
- 移除其中的元素后能够自动不缺的布局
三个属性:
属性名称 | 数据类型 | 可取值 | 描述 |
---|---|---|---|
Orientation | Orientation枚举 | Horizontal Vertical |
决定内部元素是横向累计还是纵向累积 |
HorizontalAlignment | HorizontalAlignment枚举 | Left Center Right Stretch |
决定内部元素水平方向向上对齐方式 |
VerticalAlignment | VerticalAlignment枚举 | Top Center Bottom Stretch |
决定垂直方向的对齐方式 |
<GroupBox Header="test" BorderBrush="Black" Margin="5">
<StackPanel>
<CheckBox Content="hello1"/>
<CheckBox Content="hello1"/>
<CheckBox Content="hello1"/>
<CheckBox Content="hello1"/>
<CheckBox Content="hello1"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button Content="确定" Width="60" Margin="5"/>
<Button Content="取消" Width="60" Margin="5"/>
</StackPanel>
</StackPanel>
</GroupBox>
5.4.4 Canvas
他有 Canvas.X 和 Cnavas.Y属性
用处:
- 一经设计基本上不会再有改动的小型布局(如图标)
- 艺术性比较强的布局
- 需要大量使用横纵坐标进行绝对定位的布局
- 依赖于横纵坐标的动画
<Canvas HorizontalAlignment="Left" Height="270" Margin="36,47,0,0" VerticalAlignment="Top" Width="300">
<TextBlock Canvas.Left="142" TextWrapping="Wrap" Text="TextBlock" Canvas.Top="100"/>
<StackPanel Height="100" Canvas.Left="38" Canvas.Top="160" Width="100"/>
<Label Content="Label" Canvas.Left="56" Canvas.Top="52"/>
</Canvas>
5.4.5 DockPanel
DockPanel内的 元素 会附加上 DockPanel.Dock 这个属性 这个属性的数据类型是 枚举 Left Top Right 和 Bottom ,根据Dock的值,DockPanel内的元素会向指定方向累积,切分DockPanel内部的剩余可用空间,就像船舶靠岸一样
DockPanel还有一个重要属性---bool 类型的 LastChideFill 他默认是 True,当他为True的时候 DockPanel的最后一个元素 DockPanel.Dock 属性会被忽略,这个元素会把剩下的空间填充满
<DockPanel >
<TextBox BorderBrush="Black" Height="25" Text="123" DockPanel.Dock="Top"/>
<TextBox BorderBrush="Black" Width="25" Text="123" DockPanel.Dock="Left"/>
<TextBox BorderBrush="Black"/>
</DockPanel>
<Grid ShowGridLines="False" Margin="10" >
<Grid.RowDefinitions>
<RowDefinition Height="25"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBox Grid.ColumnSpan="3" BorderBrush="Black"/>
<TextBox Grid.Row="1" BorderBrush="Black"/>
<GridSplitter Grid.Row="1" Grid.Column="1"
VerticalAlignment="Stretch" HorizontalAlignment="Center"
Width="5" Background="Gray"
ShowsPreview="True"/>
<TextBox Grid.Row="1" Grid.Column="2" BorderBrush="Black"/>
</Grid>
5.4.6 WrapPanel
WrapPanel 内部采用的是流式布局, WrapPanel使用Orientation属性来控制流的延伸方向,使用 HorizontalAlignment和VerticalAlignment两个属性控制内部控件的对齐
在流延伸的方向上,WrapPanel 会排列尽可能多的控件,排不下的会新起一排继续排列
<WrapPanel>
<Button Width="50" Height="50" Content="OK"/>
<Button Width="50" Height="50" Content="OK"/>
<Button Width="50" Height="50" Content="OK"/>
</WrapPanel>
标签:控件,元素,第一,标签,XAML,深入浅出,System,WPF,属性 来源: https://www.cnblogs.com/lddragon/p/16519626.html