一步一步学Silverlight 2系列(3):界面布局

概述

Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言Visual Basic, Visual C#, IronRuby, Ironpython,对JSON、Web Service、WCF以及Sockets的支持等一系列新的特性。《一步一步学Silverlight 2系列》文章带您快速进入Silverlight 2开发。

本文为系列文章第三篇,学习Silverlight 2中的界面布局,Silverlight 2中新增加了Grid和Panel两个布局容器,使得界面布局更加的强大和灵活。

Canvas面板

Canvas是在Silverlight 1.0时代就有的一种基础布局面板,它采用绝对坐标定位。可以使用附加属性(Attached Property)对Canvas中的元素进行定位,通过附加属性我们指定控件相对于其直接父容器Canvas 控件的上、下、左、右坐标的位置。如下面的XAML声明了两个矩形,它们分别相对于父容器Canvas的左边距是50,相对于父容器Canvas的上边距分别是50和150:

TerryLee_Silverlight2_0020

运行后界面的效果如下所示:

TerryLee_Silverlight2_0021

除了上面我们用到的Canvas.Top和Canvas.Left两个附加属性外,还有一个Canvas.ZIndex附加属性。如果指定了两个控件相对于父容器Canvas同样的边距,则后面声明的控件父覆盖前面声明的控件。这时我们可以使用Canvas.ZIndex属性来改变它们的显示顺序,如下面的XAML声明:

<Canvas Background="#46461F">
    <Rectangle Fill="#0099FF" Width="160" Height="80"
               Canvas.Top="100" Canvas.Left="100">
    
    <Rectangle Fill="#FF9900" Width="160" Height="80"
             Canvas.Top="100" Canvas.Left="100"/>
</Canvas>

指定两个矩形相对于父容器Canvas的边距相同,这时默认的后声明的橙色矩形会覆盖蓝色矩形:

TerryLee_Silverlight2_0023

指定Canvas.ZIndex为1

<Canvas Background="#46461F">
    <Rectangle Fill="#0099FF" Width="160" Height="80"
               Canvas.Top="100" Canvas.Left="100" Canvas.ZIndex="1"/>
    
    <Rectangle Fill="#FF9900" Width="160" Height="80"
             Canvas.Top="100" Canvas.Left="100"/>
</Canvas>

将会让蓝色矩形显示在上面,值最大的显示在最上面:

TerryLee_Silverlight2_0024

StackPanel

StackPanel支持用行或列的方式来进行页面布局,默认情况下所有的子元素会垂直的排列显示,如下面的XAML声明三个矩形:

<StackPanel Background="#46461F">
    <Rectangle Fill="#0099FF" Stroke="White"
               Width="100" Height="50" Margin="10"/>
    <Rectangle Fill="#0099FF" Stroke="White"
               Width="100" Height="50" Margin="10"/>
    <Rectangle Fill="#0099FF" Stroke="White"
               Width="100" Height="50" Margin="10"/>
</StackPanel>

运行后在界面显示效果如下:

TerryLee_Silverlight2_0025

当然我们也可以指定为水平排列,通过Orientation属性指定:

<StackPanel Background="#46461F" Orientation="Horizontal">
    <Rectangle Fill="#0099FF" Stroke="White"
               Width="100" Height="50" Margin="10"/>
    <Rectangle Fill="#0099FF" Stroke="White"
               Width="100" Height="50" Margin="10"/>
    <Rectangle Fill="#0099FF" Stroke="White"
               Width="100" Height="50" Margin="10"/>
</StackPanel>

运行后界面显示效果如下:

TerryLee_Silverlight2_0026

在这里为了让各个控件之间有一定的距离,使用了Margin属性,该属性类似于HTML中的Margin。

Grid

Grid控件类似与HTML中的Table,只不过子元素不用放在单元格中。通过<Grid.RowDefinitions> 和 <Grid.ColumnDefinitions>来定义Grid的行和列,使用Grid.Row和Grid.Column两个附加属性指定子元素在Grid中显示的位置,这是一种非常灵活的布局方式。如下面的XAML声明:

<Grid x:Name="LayoutRoot" Background="#46461F" ShowGridLines="True">
    <Grid.RowDefinitions>
        <RowDefinition Height="120"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="100"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <TextBlock Grid.Row="0" Grid.Column="0" Text="UserName:" VerticalAlignment="Center" Foreground="White"></TextBlock>
    <TextBlock Grid.Row="1" Grid.Column="0" Text="Password:" VerticalAlignment="Center" Foreground="White"></TextBlock>
    <TextBox Grid.Row="0" Grid.Column="1" Width="200" Height="30" HorizontalAlignment="Left"></TextBox>
    <TextBox Grid.Row="1" Grid.Column="1" Width="200" Height="30" HorizontalAlignment="Left"></TextBox>
</Grid>

定义一个两行两列的Grid,做一个简单的用户登录的布局,为了明显起见,把ShowGridLines属性设为True,以便能够显示出边框线。同时,我们指定了第一行的高度为120,而第二行的则是剩余的高度,用*来指定。运行后效果如下:

TerryLee_Silverlight2_0027

综合实例

分别了解了上面的三个布局控件,接下来我们看一个综合实例,如何完成如下的一个取色器:

TerryLee_Silverlight2_0028

首先我们添加一个两行两列的Grid控件,分别指定行高和列宽:

<Grid x:Name="LayoutRoot" Background="White">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="260" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="120" />
        <RowDefinition Height="120" />
    </Grid.RowDefinitions>
</Grid>

添加颜色显示区域,用一个矩形显示,放入Grid的第0行第1列:

<Rectangle Grid.Row="0" Grid.Column="1" x:Name="PreviewColor"
                   Fill="#FF6600" Margin="10" Stroke="#666666" StrokeThickness="2" />

再添加颜色值显示区,嵌套一个StackPanel控件,让它里面的子控件垂直显示:

<StackPanel Grid.Row="1" Grid.Column="1" >
    <TextBlock FontSize="12">Color</TextBlock>
    <TextBox x:Name="HexColor" Width="160" Height="30" Text="#FF6600" Margin="10,5" FontSize="11"/>
</StackPanel>

左边用四个Silder控件和四个TextBlock控件显示,需要对Grid的行进行合并Grid.RowSpan属性:

<StackPanel Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" VerticalAlignment="Center">
   <TextBlock Text="Alpha" FontSize="12" Margin="10,15,0,0"/>
   <Slider x:Name="AlphaSlider" Margin="20,0,10,0" Maximum="255" Value="255" ValueChanged="RedSlider_ValueChanged"/>
   <TextBlock Text="Red" FontSize="12" Margin="10,15,0,0"/>
   <Slider x:Name="RedSlider" Margin="20,0,10,0" Maximum="255" Value="255" ValueChanged="RedSlider_ValueChanged"/>
   <TextBlock Text="Green" FontSize="12" Margin="10,15,0,0"/>
   <Slider x:Name="GreenSlider" Margin="20,0,10,0" Maximum="255" Value="102" ValueChanged="RedSlider_ValueChanged"/>
   <TextBlock Text="Blue" FontSize="12" Margin="10,15,0,0"/>
   <Slider x:Name="BlueSlider" Margin="20,0,10,0" Maximum="255" Value="0" ValueChanged="RedSlider_ValueChanged"/>
</StackPanel>

这样我们就完成了上面这样相对复杂的界面布局,对Slider控件添加事件处理程序:

private void RedSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
    Color color = Color.FromArgb((byte)AlphaSlider.Value, (byte)RedSlider.Value, (byte)GreenSlider.Value, (byte)BlueSlider.Value);

    PreviewColor.Fill = new SolidColorBrush(color);
    HexColor.Text = color.ToString();
}
运行后,可以选取不同的颜色值:

TerryLee_Silverlight2_0029

结束语

关于界面布局就说到这里,在Silverlight 2中,通过上面的三种布局控件相结合,可以进行非常强大和灵活的界面布局。

下一篇:一步一步学Silverlight 2系列(4):鼠标事件处理

作者:TerryLee
出处:http://terrylee.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。
Tag标签: Silverlight,XAML

posted on 2008-03-07 21:27 TerryLee 阅读(7105) 评论(41)  编辑 收藏 所属分类: Silverlight

评论

#1楼  2008-03-07 22:12 生鱼片      

跟着这系列学习了   回复  引用  查看    

#2楼 [楼主] 2008-03-07 22:22 TerryLee      

@生鱼片
呵呵,我也是利用这个周末好好看看,争取多写几篇出来:)   回复  引用  查看    

#3楼  2008-03-20 14:20 Ben@ [未注册用户]

为什么不能直接从Toolbox中拖放控件?   回复  引用    

#4楼 [楼主] 2008-03-20 18:21 TerryLee      

@Ben@
目前Beta 1不支持,但是可以拖动到Toolbox中   回复  引用  查看    

#5楼  2008-03-24 15:59 *o* [未注册用户]

GRID空件是放在USERCONTROL中的吗?   回复  引用    

#6楼  2008-03-24 16:09 *o* [未注册用户]

你好
我想问下怎么我预览在浏览器中是什么也不显示呢?   回复  引用    

#7楼 [楼主] 2008-03-24 21:17 TerryLee      

@*o*
是的   回复  引用  查看    

#8楼 [楼主] 2008-03-24 21:18 TerryLee      

@*o*
什么代码在浏览器中没有显示?   回复  引用  查看    

#9楼  2008-03-25 12:49 romce      

学习。。。。   回复  引用  查看    

#10楼 [楼主] 2008-03-25 22:21 TerryLee      

@romce
:)   回复  引用  查看    

#11楼  2008-03-26 13:50 jerrywang [未注册用户]

加入Slider部分的代码后,页面显示一片空白。
还有为什么每次刷新页面都会向search.microsoft.com发送数据?   回复  引用    

#12楼  2008-03-27 12:30 *o* [未注册用户]

谢谢你的帮助 仔细看了下 解决了问题   回复  引用    

#13楼  2008-04-06 16:03 樱山飞雪 [未注册用户]

NICE! 好好学习了   回复  引用    

#14楼  2008-04-14 17:10 juliankim [未注册用户]

有一个问题 怎么才能让slider在拖动时实时显示其tooltip?
找来找去没找到方法,鼠标按下去tooltip就消失了,望楼主赐教。。   回复  引用    

#15楼  2008-04-23 18:30 aito      

--引用--------------------------------------------------
*o*: 你好
我想问下怎么我预览在浏览器中是什么也不显示呢?
--------------------------------------------------------
--引用--------------------------------------------------
TerryLee: @*o*
是的
--------------------------------------------------------
楼主你的效果不是在流览器流览的么?怎么我的流览也是什么都看不到的?是不是代码放错了地方了?   回复  引用  查看    

#16楼  2008-04-24 09:54 外城      

学习了!   回复  引用  查看    

#17楼  2008-05-30 17:57 wxj [未注册用户]

--引用--------------------------------------------------
jerrywang: 加入Slider部分的代码后,页面显示一片空白。
还有为什么每次刷新页面都会向search.microsoft.com发送数据?
--------------------------------------------------------
我的也是,请问你是怎么解决的?谢谢
  回复  引用    

#18楼  2008-06-11 12:53 小牛大牛      

不喜欢Grid的定义行和列的方式,直接用Html那种方式不好得很吗??
把行定义和列定义单独分开,看着多别扭.我要想弄个东西,还得先看行号和列号是多少,不爽,极不爽!
楼主很棒,学习中!   回复  引用  查看    

#19楼  2008-06-16 23:30 房客      

我提个问题:
我在写代码时不小心写成这样:
<Slider x:Name="AlphaSlider" Maximum="255" Minimum="255" Margin="20,10" ValueChanged="Slider_ValueChanged"></Slider>
就是把Minimum属性赋值了,在调试的时候,就触发了ValueChanged事件了。这是为何?
如果说初始指定Minimum会触发ValueChanged,那为何指定Maximum却不会触发ValueChanged?
vs2008 sp1 + silverlist2.0 beat2

  回复  引用  查看    

#20楼  2008-06-16 23:38 房客      

调试了下,找到原因了。
应该是slider的默认的value是0,当设置minimum的值不为0时,将更改其value为minimum。这时会触发valuechanged.
因为我不指定minimum时,去指定默认value时也会触发valuechanged,如下代码:
<Slider x:Name="AlphaSlider" Maximum="255" Minimum="0" Value="10" Margin="20,10" ValueChanged="Slider_ValueChanged"></Slider>

事件的先后顺序应该是设置slider的value,会同时发生于构造slider。
这时,就会出现一个问题,事件先后顺序的问题。
一般情况下,指定slider默认值是很普通的事情。这时去触发valuechanged的事件时,由于slider还未构造完成,没有呈现在控件中,触发了valuechanged的事件,一旦在valuechanged的事件处理方法中,引用了slider实例,就会出现对象尚未实例化的错误。

不知道这是不是一个bug.   回复  引用  查看    

#21楼  2008-06-23 17:01 Zhang Peng [未注册用户]

我不知道为什么,按照上面的代码,在我的机器上总是valueChanged事件在实例化slider之前被调用,因而总报null错误.
我的处理方式是在valueChanged方法中加入判断.
不知道这个原因是如何引起的,是因为我用的Silverlight Beta 2吗?   回复  引用    

#22楼  2008-06-23 18:33 Wang-JF [未注册用户]

找到原因了,和Maximum,Minimum无关,楼主的代码中4个RedSlider都有设置Value,如Value="102",这个在silverlight2下会触发RedSlider_ValueChanged事件,从而导致NULL的异常,只要在xaml设计页,拿掉value的赋值即可   回复  引用    

#23楼  2008-06-23 18:34 Wang-JF [未注册用户]

补充是silverlight2 beta2 !
beta1没试过   回复  引用    

#24楼  2008-07-05 15:41 郑州-袁金辉      

--引用--------------------------------------------------
Wang-JF: 找到原因了,和Maximum,Minimum无关,楼主的代码中4个RedSlider都有设置Value,如Value=&quot;102&quot;,这个在silverlight2下会触发RedSlider_ValueChanged事件,从而导致NULL的异常,只要在xaml设计页,拿掉value的赋值即可
--------------------------------------------------------
遇到了同样的问题,用此方法解决了,多谢   回复  引用  查看    

#25楼 [楼主] 2008-07-06 22:16 TerryLee      

@郑州-袁金辉
@Wang-JF
我这个例子是在Beta 1下面写的!   回复  引用  查看    

#26楼  2008-07-14 20:37 Kenny tian      

不知道大家这个问题是怎么解决的,Color框里的值是#00009A00

最前面两位是Alpha的值,怎么去掉?   回复  引用  查看    

#27楼  2008-07-18 17:32 StrongBird [未注册用户]

请教Terry一个问题:我用WPF XBAP工程就可以实现这些东西吗?请问SilverLight实现的和XBAP的有什么区别?   回复  引用    

#28楼 [楼主] 2008-07-21 10:17 TerryLee      

@Kenny tian
为什么要去掉前两位呢?   回复  引用  查看    

#29楼 [楼主] 2008-07-21 10:17 TerryLee      

@StrongBird
WPF跟这还不一样,Silverlight是WPF的一个子集,用于在Web上的实现   回复  引用  查看    

#30楼  2008-07-21 10:53 StrongBird [未注册用户]

@TerryLee
明白了,我的理解是Silverlight Runtime实际是一个精简版的framework(WPF 的子集),其职责相当于在Web页面中支持内嵌类似flash这样的RIA模型。
不知道我的理解正不正确,但是如果是这样的话,似乎Silverlight和它的前身代码WPF/E(WPF Everywhere)的定位还是有一定差距啊呵呵。   回复  引用    

#31楼  2008-07-25 14:29 不若相忘于江湖      

楼上各位正解。
  回复  引用  查看    


标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2008-03-08 00:49 编辑过
 
另存  打印
 


导航

公告

  • 网名:TerryLee
  • 本名:李会军
  • 位置:中国北京 Ethos
  • 联系方式:
  • 访问我的个人主页

 MVP配置

 个人主页

 版权声明

  • 本站采用创作共用许可 署名,非商业

绿色通道

IT新闻

统计

与我联系

留言簿(323)

我的标签

随笔分类

随笔档案

个人站点

关注项目

好的网站

我的好友

搜索

积分与排名

阅读排行榜

评论排行榜