面板类控件
面板类控件直接和程序的布局有关,除了布局之外,面板类控件还起到了WinForm中容器的作用,就像是将一些控件放到一个面板中,达到组织管理的目的,这也是面板类控件的一个常用的功能。
面板类控件一共有5类:
Grid、Canvas、StackPanel、WrapPanel、Border
Grid
Grid控件用来布局,他的作用就相当于ASP.NET中的table的作用,使用它,可以创建n行n列,在每一个单元格中进行控件的布局,Grid的行和列一般是不会显示的,但也可以使用属性ShowGridLines来使其显示。
在我们创建一个项目的时候,MainPage.xaml中系统就为我们默认的使用了Grid,如一个名为“LayoutRoot”的<Grid x:Name="LayoutRoot"></Grid>的Grid控件,它是用来放置页面中所有控件的基础Grid。在它之中,存在一个StackPanel控件用来存放程序名和标题,除此之外还存在一个名为“ContentPanel”的<Grid x:Name="ContentPanel"></Grid>,用来程序员自定义其他控件。我们可以为Grid定义行和列,行的定义为<Grid.RowDefinition>,列的定义为<Grid.ColumnDefination>。
至于行列的创建方式:
- 一种是直接在属性设计器中的ColumnDefinitions或者RowDefinitions属性中直接编辑,编辑的时候有三个属性可以设置,MinWidth属性设置最小尺寸,一般为默认值0,MaxWidth属性设置最大尺寸,一般为默认值Infinity(无穷大)。而我们需要关心的是Width属性,这就是我们在视图中关心的,设置方式如下。
- 另一种就是我们可以书写<Grid.RowDefinition>与<Grid.ColumnDefination>的标签并在其中设置属性。至于属性,RowDefinition的属性是Height,而ColumnDefinition的属性是Width,这些属性的书写有三种方式,以Height为例:Height="200"、Height="Auto"、Height="*",含义分别为:行(列)按照给定的尺寸设置、行列按照内容的实际尺寸设置(其实就是我们自己拉伸尺寸的值)、行(列)按照剩余的可用空间来分配。
假设现在我们设置了3行3列的Grid,如果想要把Button放在2行3列,那么在Button中可以这样写<Button Grid.Row="1" Grid.Column="2"/>,这样就行了(在这里行列均是从零开始)。
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的背景色发生随机变化。所以布局为:
<!--ContentPanel - 在此处放置其他内容--> <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中,并查看布局情况。
前台:
<!--ContentPanel - 在此处放置其他内容--> <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事件模拟单击事件。先看代码,等等看效果。
<!--ContentPanel - 在此处放置其他内容--> <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("确定"); }
效果: