XAML (Extensible Application Markup Language) 可扩展应用程序标记语言是一种基于 XML 的标记语言,以声明形式实现应用程序的外观。 通常用它创建窗口、对话框、页和用户控件,并填充控件、形状和图形,且自身即可实现动画效果(通过blend
生成XAML)。
XAML中每个标签在运行时都会创建一个实例。 例如, Window
元素被转换为 Window
类的实例,该类的 Title
属性是 Title
特性的值。
命名空间 xmlns (XML Namespace)
xmlns[:自定义映射名] = "对应的命名空间"
例如想引入类库文件MyClass.dll中的命名空间ABC,则
xmlns:abc="clr-namespace:ABC;assembly=MyClass"
//效果类似于 using ABC = abc;
用于声明命名空间,如下<Window>和<Grid>均属于xmlns
声明的默认命名空间,x:Class
中的内容则属于xmlns:x
声明的命名空间。其中配置的内容并非网址,而是一个XAML内置的一个对应关系,该内容对应了多个命名空间。
通过在AssemblyInfo.cs
中添加[assembly:xmlnsDefinition("www.xxx.com","wpfLibrary")]
也可以将自己的网址设置成一个命名空间的对应。
<Window x:Class="WpfTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
</Grid>
</Window>
经过声明的命名空间下的类可以直接作为标签被使用
<abc:Tab>...</abc:Tab>
为XAML的对象属性赋值
- 使用字符串进行简单赋值
<Rectangle Grid.ColumnSpan="2" Fill="#F00" HorizontalAlignment="Left" Height="100" VerticalAlignment="Top" Width="100"/>
- 使用属性元素进行复杂赋值
当属性是复杂对象时有优势
<Rectangle Grid.ColumnSpan="2" HorizontalAlignment="Left" Height="100" VerticalAlignment="Top" Width="100">
<Rectangle.Fill>
<SolidColorBrush Color="#F0F"/>
</Rectangle.Fill>
</Rectangle>
- 标记扩展
通过"{Binding XXX=XXX}"
的方式将TextBox
的属性依赖在Slider
的Value
上
<Slider Name="slider1" Height="30" Width="100"/>
<TextBox Text="{Binding ElementName=slider1,Path=Value,Mode=OneWay}" Height="30" TextWrapping="Wrap" Width="100"/>
或改用属性元素
<TextBox Text="{Binding ElementName=slider1,Path=Value,Mode=OneWay}" Height="30" TextWrapping="Wrap" Width="100">
<TextBox.Text>
<Binding ElementName=slider1,Path=Value,Mode=OneWay>
</TextBox.Text>
</TextBox>
X名称空间中的属性
x:Class
x:Class
本身不是对象的成员,而是从x
命名空间中拿出来硬贴上去的,且只能用于根节点
拥有x:Class
的标签会自动解析为一个类名为x:Class
的值的partial
类(称为代码隐藏类),其嵌套的标签会被解析为其派生类,编译时会和.cs
文件中的同名partial
类合并。
拥有x:Class
的标签解析后的类自动拥有InitializeComponent
方法,用于初始化窗体组件,将标记中定义的 UI 与代码隐藏类合并在一起。
通过Name
属性在.cs
中获取xaml
中对应元素。
- x:ClassModifier
只能给有x:Class
属性的标签添加,用于设置该类的访问权限
x:Name
通常可与Name
互换。
当一个标签具有x:Name
时,除了生成对应实例外还会为这个实例声明一个引用变量,变量名即x:Name
的值
- x:FieldModifier
拥有x:Name
的XAML标签实例,访问权限默认为internal
。通过x:FieldModifier
可以设置为public
等。
x:Key 与 资源
为资源字典贴上用于检索的索引。
<Window xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Window.Resources>
<sys:String x:Key="myString">hello this is String</sys:String>
</Window.Resources>
<TextBox Text="{StaticResource ResourceKey=myString}"/>
</Window>
在方法中也能获取资源
String myString = this.FindResource("myString") as String;
- x:Shared
若为true
,每次通过x:Key
获取的是同一个对象,否则为一个新的副本。默认为true
。
x名称空间中的标记扩展
x:Type,x:Null 与 Style
当需要指定某值为null
时使用x:Null
如已经指定了所有Button
的Style
,但有一个不需采用该Style
时
<Window.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Width" Value="50"></Setter>
</Style>
</Window.Resources>
<Button Style="{x:Null}"/>
x:Static
在XAML中直接使用类的static成员
<Button Content="{x:Static local:MainWindow.ButtonContent}"/>
...
public static string ButtonContent= "Click Me";
x:Array 与 ListBox
x:Array
用于暴露一个指定类型的ArrayList
/List
实例
<ListBox>
<ListBoxItem>1</ListBoxItem>
<ListBoxItem>2</ListBoxItem>
</ListBox>
等价于
<ListBox Name="listbox"></ListBox>
...
listbox.ItemsSource = new List<string>(new []{"1","2"});
等价于
<ListBox>
<ListBox.ItemsSource>
<x:Array Type="sys:String">
<sys:String>1</sys:String>
<sys:String>2</sys:String>
</x:Array>
</ListBox.ItemsSource>
</ListBox>
控件与布局
有些控件的内容是一个集合,如StackPanel
的内容属性是Children
,ListBox
的内容属性是Items
,当通过属性元素赋值时可以省略该内容属性的标签。
ContentControl基类
包括Window
, ScrollViewer
,各种Button
,CheckBox
等
- 均具有内容属性
Content
- 内部最多只能包含一个元素
Button
表示 Windows 按钮控件,该按钮对 Click
事件作出反应
- Click 绑定事件
- ClickMode 触发方式
- Hover => mouseover
- Press => mousedown
- Release => mouseup
ItemsControl 基类
包括Menu
, ContextMenu
,ComboBox
,ListBox
,TabControl
等
- 内容属性为
Items
或ItemsSource
- 内容应为一个集合,且会自动被对应的条目容器进行包装
如ListBox
的条目容器为ListBoxItem
,因此以下两种写法等效
<ListBox>
<Button Content="Click Me"/>
</ListBox>
<ListBox>
<ListBoxItem>
<Button Content="Click Me"/>
</ListBoxItem>
</ListBox>
- DisplayMemberPath 属性
规定展示数组中每个对象的某个属性
TextBlock 和 TextBox
用于文本展示
- TextBlock
具有丰富的格式/排版控制
内容属性为Inlines
- TextBox
支持用户自己编辑
内容属性为Text
Panel基类与UI布局
内容属性均为Children
Grid 网格
类似Table,适用于行列对齐等
默认ColumnDefinition
拥有Width="1*"
,RowDefinition
拥有Height="1*"
- 取值若为
px
,px
可省略 - 若为
Auto
,则由其内容撑开,无内容则不占空间(可用Min-Width
/Min-Height
设置最小值) - 若为
*
,则由剩余空间按值分配(类似于flex的伸缩占比)
<Grid Name="myGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="100px"></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1">hello</TextBlock>
</Grid>
...
myGrid.ColumnDefinitions.Add(new ColumnDefinition());
StackPanel
类似<div style="display:flex;"></div>
- Orientation 元素排列方式
Horizontal/Vertical - HorizontalAlignment 元素对齐方式
Left/Center/Right/Stretch - VerticalAlignment 元素对齐方式
Top/Center/Bottom/Stretch
Canvas
类似<div style="position:absolute;"></div>
其中的每个标签通过设置Canvas.Left
和Canvas.Top
属性来确定位置
DockPanel
内部元素通过DockPanel.Dock
选择泊靠方向(类似浮动,但具有四个方向)
- 最后一个子元素的
DockPanel.Dock
会被忽略,将尽量撑满整个DockPanel
(可通过设置LastChildFill="false"
禁用该功能)
<DockPanel>
<TextBox BorderBrush="Blue" Height="100" DockPanel.Dock="Top">1</TextBox>
<TextBox BorderBrush="Blue" Width="100" DockPanel.Dock="Left">2</TextBox>
<TextBox BorderBrush="Blue">3</TextBox>
</DockPanel>
WrapPanel
流式布局,排满一行自动换行(类似子元素全为inline-block
)
通过HorizontalAlignment
和VerticalAlignment
可以设置子元素整体在WrapPanel
中的位置(不影响子元素间的相对位置关系)
<WrapPanel HorizontalAlignment="Right" VerticalAlignment="Center">
<TextBox BorderBrush="Red" Width="100" Height="100">1</TextBox>
<TextBox BorderBrush="Red" Width="100" Height="100">2</TextBox>
<TextBox BorderBrush="Red" Width="100" Height="100">3</TextBox>
<TextBox BorderBrush="Red" Width="100" Height="100">4</TextBox>
<TextBox BorderBrush="Red" Width="100" Height="100">5</TextBox>
</WrapPanel>
动态修改XAML
Grid grid = new Grid();
grid.ColumnDefinitions.Add(new ColumnDefinition());
grid.ColumnDefinitions.Add(new ColumnDefinition());
grid.ColumnDefinitions.Add(new ColumnDefinition());
grid.RowDefinitions.Add(new RowDefinition());
grid.RowDefinitions.Add(new RowDefinition());
grid.RowDefinitions.Add(new RowDefinition());
Button button = new Button() { Content="hello"};
Grid.SetColumn(button, 1);
Grid.SetRow(button, 1);
grid.Children.Add(button);
Content = grid;
事件处理器
一个XAML标签对应一个对象,标签的一部分属性对应对象的属性,另一部分则对应对象的事件。如:
<Button Name="button" Click="Button_Click"/>
约等于
private void Button_Click(object sender, RoutedEventArgs e){}
Button button = new Button();
button.click+=new RoutedEventHandler(Button_Click);
在事件中获取对象可以直接使用x:Name
的值,也可以使用形参中的sender
(即为事件的绑定者),配合.Children[0]
等选取标签。
定位
- Margin
按照左上右下依次定义,默认为"0,0,0,0"
- HorizontalAlignment
水平定位,决定了Margin优先用左右哪个值,默认为"Left"
- VerticalAlignment
垂直定位,决定了Margin优先用上下哪个值,默认为"Top"