面板类控件直接和程序的布局有关,除了布局之外,面板类控件还起到了WinForm中容器的作用,就像是将一些控件放到一个面板中,达到组织管理的目的,这也是面板类控件的一个常用的功能。
面板类控件一共有5类:
Grid、Canvas、StackPanel、WrapPanel、Border
Grid
Grid控件用来布局,他的作用就相当于ASP.NET中的table的作用,使用它,可以创建n行n列,在每一个单元格中进行控件的布局,Grid的行和列一般是不会显示的,但也可以使用属性ShowGridLines来使其显示。
在我们创建一个项目的时候,MainPage.xaml中系统就为我们默认的使用了Grid,如一个名为“LayoutRoot”的的Grid控件,它是用来放置页面中所有控件的基础Grid。在它之中,存在
一个StackPanel控件用来存放程序名和标题,除此之外还存在一个名为“ContentPanel”的,用来程序员自定义其他控件。我们可以为Grid定义行和列,行的定义
为,列的定义为。
至于行列的创建方式:
- 一种是直接在属性设计器中的ColumnDefinitions或
者RowDefinitions属性中直接编辑,编辑的时候有三个属性可以设置,MinWidth属性设置最小尺寸,一般为默认值0,MaxWidth属
性设置最大尺寸,一般为默认值Infinity(无穷大)。而我们需要关心的是Width属性,这就是我们在视图中关心的,设置方式如下。
- 另一种就是我们可以书写与的标签并在其中设置属性。至于属性,RowDefinition的属性是Height,而ColumnDefinition的属性是Width,这些属性的书写有三种方式,以Height为例:Height="200"、Height="Auto"、Height="*",含义分别为:行(列)按照给定的尺寸设置、行列按照内容的实际尺寸设置(其实就是我们自己拉伸尺寸的值)、行(列)按照剩余的可用空间来分配。
假设现在我们设置了3行3列的Grid,如果想要把Button放在2行3列,那么在Button中可以这样写,这样就行了(在这里行列均是从零开始)。
Canvas
Canvas相当于是一行一列的Grid,用绝对坐标对放置其中的控件进行布局和管理。
这其实就是传统意义上的画布,在这个控件里头我们可以按照绝对坐标随意放置控件。我们可以在其中放置一些控件来生成自己的有特色的效果。比如说生成自己的一个对话框。但是由于绝对定位不考虑浏览器窗口的大小或浏览器大小调整,因此一般最好使用 Grid 或 StackPanel 作为容器。
StackPanel
StackPanel使用相对位置对控件进行管理。它使用的是流方式进行元素的布局,也就是说,我们不能随意改变StackPanel中的其他控件的位
置。这一点类似于Android中的线性布局。其实在我们Visual
Studio中生成的项目中,“TitlePanel”就是使用StackPanel进行布局的。同时,类似于Android中线性布局时可以是纵向也可
以是横向,只要设置Orientation属性就行了, Orientation 属性的默认值为 Vertical。
StackPanel 中内容的 HorizontalAlignment 和 VerticalAlignment 默认值均为 Stretch。
注意:
StackPanel使用线性布局,通俗的意思就是只能在一条直线上对控件进行布局,如果控件的数量使得控件超出了StackPanel的显示范围,系统将会应用蒙版,我们只要理解为不能正常显示就行了,所以在布局的时候要考虑到这些因素。
WrapPanel
WrapPanel控件是toolkit中的一个控件,一般不在工具箱中显示,只要右键“选择项”,找到WrapPanel添加就会出现在工具箱中。这个
控件的使用和StackPanel控件类似,只是它的特性就像它的名字一样,布局中的控件若是超出了WrapPanel的范围,会自动Wrap,即换行,
这是比StackPanel特别的地方。
Border
Border为对象提供一个尺寸可变的边框。需要注意的是,包含在边框控件中的控件只能有一个元素。如果想包含多个元素,只需要使用其他容器控件将各种元素包含起来就行了。如StackPanel。
最后
所以操作面板类控件也可以在后台进行。可以指定 Border
的基本属性,方法是设置其 Width、Height、BorderThickness 以及 Background 颜色。 此外,您还可以通过设置
CornerRadius 属性以将边框的各角改为圆角,并且可以通过设置 Padding 属性以在 Border 中定位对象。
一个常识就是一般在xaml中看得到的控件或者属性都会有相应的类或属性与之对应。
下面就用一个简单例子页面来练习一下这些面板类控件的使用。
Grid例子
新建一个页面,叫做“Grid.xaml”。
在这个页面中设置三行三列的Grid表格,在每一个单元格中放置一个StackPanel,在后台代码中控制这些StackPanel的背景色,并使用线
程,每一个StackPanel设置一个后台线程,每隔0.5秒使每个StackPanel的背景色发生随机变化。所以布局为:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0" ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
Grid.ColumnDefinitions>
<StackPanel Name="stackPanel00" Grid.Row="0" Grid.Column="0"/>
<StackPanel Name="stackPanel01" Grid.Row="0" Grid.Column="1"/>
<StackPanel Name="stackPanel02" Grid.Row="0" Grid.Column="2"/>
<StackPanel Name="stackPanel10" Grid.Row="1" Grid.Column="0"/>
<StackPanel Name="stackPanel11" Grid.Row="1" Grid.Column="1"/>
<StackPanel Name="stackPanel12" Grid.Row="1" Grid.Column="2"/>
<StackPanel Name="stackPanel20" Grid.Row="2" Grid.Column="0"/>
<StackPanel Name="stackPanel21" Grid.Row="2" Grid.Column="1"/>
<StackPanel Name="stackPanel22" Grid.Row="2" Grid.Column="2"/>
Grid>
在后台中,首先定义一个随机数实例,生成颜色Color随机的ARGB值,定义委托,实现后台线程与UI线程的交互,再定义字符串数组变量,用来解析StackPanel的名字,
Random myRandom = new Random();
private bool flag = true;
delegate void MyDelegate(string s);
MyDelegate myDelegate;
string[] myStr = {"00","01","02","10","11","12","20","21","22" };
定义页面读取事件用来创建线程,
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
for (int i = 0; i < myStr.Length ; i++)
{
Thread myThread = new Thread(new ParameterizedThreadStart(Change));
myThread.Name = "";
myThread.IsBackground = true;//设置为后台运行的线程
myThread.Start(myStr[i]);//线程启动
}
}
书写后台线程与UI线程的交互
private void Change(object s)
{
while (true)
{
myDelegate = ChangeUIChecked;//委托
this.Dispatcher.BeginInvoke(myDelegate,s);
Thread.Sleep((int)(0.5 * 1000));//休眠,模仿规定时间间隔
}
}
private void ChangeUIChecked(object s)
{
SolidColorBrush myBrush = new SolidColorBrush();
Color myColor = new Color();
myColor.A = (Byte)myRandom.Next(0, 256);
myColor.R= (Byte)myRandom.Next(0, 256);
myColor.G = (Byte)myRandom.Next(0, 256);
myColor.B = (Byte)myRandom.Next(0, 256);
myBrush.Color = myColor;
//((StackPanel)(ContentPanel.FindName("stackPanel" + s.ToString()))).Background = myBrush ;
((System.Windows.Controls.StackPanel)(ContentPanel.FindName("stackPanel" + s.ToString()))).Background = myBrush;
}
在运行的时候就是每隔0.5秒颜色随机变化。
StackPanel例子
新建一个页面,叫做“StackPanel.xaml”。使用后台代码随机生成多个TextBlock来放置在StackPanel中,并查看布局情况。
前台:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel Height="230" HorizontalAlignment="Left"
Margin="6,6,0,0"
Name="stackPanelHorizontal" VerticalAlignment="Top"
Width="440"
Orientation="Horizontal">
StackPanel>
<StackPanel Height="230" HorizontalAlignment="Left"
Margin="6,340,0,0"
Name="stackPanelVertical" VerticalAlignment="Top"
Width="440"
Orientation="Vertical">
StackPanel>
后台:
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
for (int i = 1; i <= 10; i++)
{
Random myRandom = new Random();
TextBlock can = new TextBlock();
can.Text = "我";
can.Width = 44;
can.Height = 23;
SolidColorBrush myBrush = new SolidColorBrush();
Color myColor = new Color();
myColor.A = (Byte)myRandom.Next(0, 256);
myColor.R = (Byte)myRandom.Next(0, 256);
myColor.G = (Byte)myRandom.Next(0, 256);
myColor.B = (Byte)myRandom.Next(0, 256);
myBrush.Color = myColor;
can.Foreground = myBrush;
this.stackPanelHorizontal.Children.Add(can);
}
for (int j = 1; j <= 10; j++)
{
Random myRandom = new Random();
TextBlock can = new TextBlock();
can.Text = "我";
can.Width = 44;
can.Height = 23;
SolidColorBrush myBrush = new SolidColorBrush();
Color myColor = new Color();
myColor.A = (Byte)myRandom.Next(0, 256);
myColor.R = (Byte)myRandom.Next(0, 256);
myColor.G = (Byte)myRandom.Next(0, 256);
myColor.B = (Byte)myRandom.Next(0, 256);
myBrush.Color = myColor;
can.Foreground = myBrush;
this.stackPanelVertical.Children.Add(can);
}
}
运行情况为:
WrapPanel例子
新建一个页面,叫做“WrapPanel.xaml”。使用与上面StackPanel相同的代码,创建90个TextBlock控件,查看运行情况。
前台:
<toolkit:WrapPanel Height="230" Name="wrapPanelHorizontal" Width="440" Orientation="Horizontal" Margin="20,160,20,378" Grid.RowSpan="2" />
<toolkit:WrapPanel Height="230" Name="wrapPanelVertical" Width="440" Orientation="Vertical" Margin="20,291,20,86" Grid.Row="1" />
后台:
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
for (int i = 1; i <= 90; i++)
{
Random myRandom = new Random();
TextBlock can = new TextBlock();
can.Text = "我";
can.Width = 44;
can.Height = 23;
SolidColorBrush myBrush = new SolidColorBrush();
Color myColor = new Color();
myColor.A = (Byte)myRandom.Next(0, 256);
myColor.R = (Byte)myRandom.Next(0, 256);
myColor.G = (Byte)myRandom.Next(0, 256);
myColor.B = (Byte)myRandom.Next(0, 256);
myBrush.Color = myColor;
can.Foreground = myBrush;
this.wrapPanelHorizontal.Children.Add(can);
}
for (int j = 1; j <= 90; j++)
{
Random myRandom = new Random();
TextBlock can = new TextBlock();
can.Text = "我";
can.Width = 44;
can.Height = 23;
SolidColorBrush myBrush = new SolidColorBrush();
Color myColor = new Color();
myColor.A = (Byte)myRandom.Next(0, 256);
myColor.R = (Byte)myRandom.Next(0, 256);
myColor.G = (Byte)myRandom.Next(0, 256);
myColor.B = (Byte)myRandom.Next(0, 256);
myBrush.Color = myColor;
can.Foreground = myBrush;
this.wrapPanelVertical.Children.Add(can);
}
}
运行情况:
Canvas与Border例子
新建一个页面,叫做“CanvasBorder.xaml”。创建一个自定义的对话框。使用Border包裹Canvas与TextBlock,给Border添加Tap事件模拟单击事件。先看代码,等等看效果。
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Border BorderBrush="Silver"
BorderThickness="1"
Height="239"
HorizontalAlignment="Left"
Margin="43,80,0,0"
Name="myBorder"
Background="Cyan"
VerticalAlignment="Top" Width="370"
Visibility="Collapsed"
>
<Canvas Height="179" Name="canvas1"
Width="302"
Background="BlanchedAlmond"
>
<StackPanel HorizontalAlignment="Center"
VerticalAlignment="Center"
Orientation="Horizontal" Canvas.Left="23" Canvas.Top="91" Width="259">
<Border
CornerRadius="20"
BorderBrush="Silver"
BorderThickness="1"
Canvas.Left="166"
Canvas.Top="86"
Height="73" Name="borderOK"
Background="OrangeRed"
Tap="borderOK_Tap"
Width="114">
<TextBlock
Height="63"
Name="textBlock1"
FontSize="46"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Text="OK" Width="81" />
Border>
StackPanel>
<Border Background="OrangeRed"
Tap="borderCan_Tap"
BorderBrush="Silver" BorderThickness="1" Canvas.Left="168" Canvas.Top="91" CornerRadius="20" Height="73"
Name="borderCan" Width="114">
<TextBlock FontSize="46" Height="63" HorizontalAlignment="Center" Name="textBlock2" Text="Can" VerticalAlignment="Center" Width="81" />
Border>
<TextBlock Canvas.Left="23"
Canvas.Top="9"
Height="56" Name="textBlock3"
Text="Are you sure?"
FontSize="40"
FontWeight="Bold"
Width="257"
Foreground="Red"/>
Canvas>
Border>
<Button Content="确定" Height="72"
HorizontalAlignment="Left"
Margin="150,529,0,0"
Name="btnOK" Click="btnOK_Click" VerticalAlignment="Top" Width="160" />
Grid>
后台给出简单的控制。
private void btnOK_Click(object sender, RoutedEventArgs e)
{
this.myBorder.Visibility = Visibility.Visible;
}
private void borderCan_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
this.myBorder.Visibility = Visibility.Collapsed;
MessageBox.Show("取消");
}
private void borderOK_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
this.myBorder.Visibility = Visibility.Collapsed;
MessageBox.Show("确定");
}
效果: