使用 Expression Blend 开发 Silverlight 2 应用 -- 初览
本文发布于 16 年前,部分内容可能已经失去参考价值。
【原文地址】First Look at Using Expression Blend with Silverlight 2
【原文发表日期】 Thursday, February 28, 2008 9:36 PM
上个星期,我写了一个《Silverlight 2 初览》的贴子,讨论即将发布的Silverlight 2 Beta1 版。在该贴子里,我给出了一些我撰写的系列教程的链接,这些教程示范了Silverlight和WPF后面的一些根本性编程概念,以及演示如何使用它们来建造一个Silverlight版的“Digg搜索客户端”应用:
在这第一套Silverlight教程里,我没有使用可视化的设计工具来建造用户界面,而是注重于展示底层的XAML UI标识(我认为这有助于更好地解释核心编程概念)。既然我们完成了对基本概念的讨论,让我们来探究一下可为我们所用,变得更有效率的一些工具。
Expression Blend对Silverlight的支持
除了即将发布Silverlight 2的Beta1版本外,我们还将发布针对这个版本的Visual Studio 2008 和 Expression Studio 的工具支持。这些工具将为建造RIA应用提供强有力的支持,是设计来允许开发人员和设计师轻松地合作开发项目的。
在今天的贴子里,我将介绍即将发布的Expression Blend 2.5三月份预览版的一些功能。在演示关于Blend是如何工作的一些基础的东西之后,我们将用它来建造一个跨平台,跨浏览器的 Silverlight IM聊天客户端:
上面的屏幕截图展示了在MAC上运行时该应用的样子,下面是在Expression Blend中该应用设计时的屏幕截图:
我们将使用Expression Blend,用可视化方法构造该应用所有的用户界面,以及使用它来干净地将UI数据绑定到代表我们的聊天会话和消息的.NET类上。
我们用来建造聊天应用的所有控件都是Silverlight 2的Beta1版的一部分。
声明:我不是设计师(也不很酷)
让我预先声明,我是个开发人员,不是个设计师。我也不是很酷。虽然我理解创建用户界面的技术,但在组合界面时,我有时会挑选很差的颜色和字体(就在我弄完本贴的屏幕截图之后,有个同事十分有助地指出,实际上有个致力于取缔我使用的一些字体和颜色的专门网站,哎,很受打击)。
我想对你们中那些有艺术细胞的人说,请对我温柔点,将你的注意力集中在我在下面演示的功能和技术上,别针对我使用的字体和颜色选择, :-)
起步: 创建一个新Silverlight 2项目
Expression Blend 和 Visual Studio 2008共享同样的解决方案/项目文件格式,这意味着你可以在VS 2008中创建新的Silverlight 项目,然后在Expression Blend 中打开,或者你也可以在Expression Blend 创建新的Silverlight 项目,然后在VS中打开。你还可以使用Expression Blend和VS 2008同时打开和编辑同个项目。
因为在我先前的Silverlight教程系列中,我已经展示了如何使用VS 2008来创建一个新Silverlight项目,让我们用这个贴子来展示如何使用Expression Blend来创建一个新的Silverlight应用。要做的话,只要在Expression Blend中选择 文件->新项目 ,选择Silverlight 2 Application图案,然后点击OK:
这会创建一个新的(与VS相兼容的)解决方案文件和Silverlight应用项目:
Blend包括了一个面向Silverlight 2应用的完整的所见即所得的设计器。在打开Silverlight页面和控件时,你可以在设计视图,XAML源码视图,或者同时显示设计视图和XAML源码视图的分割视图之间转换设计表面(支持同步编辑)。在上面我们使用了分割视图这个选项。
理解一些基本的东西:往表面上加控件
Expression Blend拥有一个与Visual Studio稍微不同的工具调色板(tool palette)(与你在像Photoshop这样的设计工具里的找到的调色板更相似些)。
Blend支持矢量图像编辑:
Blend还支持添加和操作控件。在放置布局控件(Grid, Stack, Canvas, Border, ScrollViewer等),文本控件(TextBox, TextBlock等)的工具箱中,有个特殊的图案,以及一个显示你最近用过的控件的图案:
点击工具调色板上最后面的">>"图案会显示可为你所用的所有的控件:
确认点击了Asset Library的右上角的“Show All(显示所有控件)”的复选框,如果你看不到你在找的控件的话。你还可以使用“搜索”文本框,来按名称过滤所显示的控件。
重要注意事项: Blend对所有控件都支持一种设计体验(无论是内置的控件还是第三方的控件或你应用引用的用户控件)。
在你从工具箱里选中一个控件后,你可以在设计表面点击,拖拉,画出控件来。你也可以把控件从asset工具拖拉到artboard上。在默认情形下,当你在设计表面上添加控件,与之交互时,你将得到自动的尺子和定位标记 (下面是一个带有内置按钮,日历和slider控件的表单):
理解其他基本的东西:操作控件属性
你可以在设计表面上选择任何对象,然后在屏幕的右手边点击“属性”面板,来定制它的属性:
在上面,我在把按钮的“背景”画刷改成渐变的深蓝(deeper blue gradient)(在“Brushes(画刷)”节点下面用红笔圈中的第三片,它允许我们配置渐变式的画刷)。
有用的小技巧: 属性窗口的上方包含一个搜索框,你可以用它来过滤可见的属性名称:
因为Silverlight和WPF中所有的UI对象都是使用矢量图像组成的,我们可以任何方式对控件进行变形,样式化,转换。例如,我们可以设置我们的按钮控件的Transform属性或者点击它的边角来旋转,倾斜,扩缩它:
这给与我们很大的威力和灵活性,来快速和轻松地定制我们想要的体验:
有用的小技巧: 你可以按住CTRL键来放大或缩小设计表面,然后使用你的鼠标的滑轮来控制放缩的深度。然后你可以通过按住空格键来移动设计表面的可见区域,这会导致手形光标的显示,然后你可以按住鼠标,用它来把当前可见的区域在屏幕上拖拉。后面这个小技巧在你放大得太多,想轻松地移动可见内容时会非常有用。
建造我们的聊天应用: 定义布局
在我先前的Silverlight教程系列中的第二部分:使用布局管理 (木野狐译)中,我曾谈到Silverlight和WPF中的布局管理系统,以及如何使用布局面板来轻松地控制应用的布局和流程。Expression Blend可以使得定义布局规则变得容易,还包括使用这些布局面板的内置工具支持。
记住,我们建造聊天应用的目标是拥有象这样的UI:
要达成这个目标,我们先在网页上定义三行的<grid>布局,我们可以这么做,把鼠标悬浮在设计表面的左边缘,然后点击我们想生成新的行定义的地方(在下图中,我已经建立了顶行的定义,用红笔圈出的光标所在表示我将点击来添加第二行定义的地方):
点击设计表面的左上角(下图红圈处)允许我们转换设计表面是处于 Canvas 布局模式还是Grid布局模式:
在Grid布局模式中时,Blend 会告诉我们某个行或某个列是否有固定的宽度,或是否与控件的尺寸成比例关系。上面的“空锁(empty locks)”表示这三行之间目前成比例关系(意味着它们会按比较增加,如果我们加大浏览器的大小的话):
如果我们点击顶部和底部的锁的话,我们可以把这些行设置成拥有固定的高度,而让中间一行填充剩下的高度:
我们要做的最后一步是点击顶部的边缘,再定义一个右手的列,我们将其设置成拥有固定的宽度(让左边那列动态地改变大小):
在做完上面的步骤之后,我们的XAML文件将有一个定义成下面这样的Grid:
有用的小技巧: 在上面,我们对我们的Silverlight应用设置了固定的宽度和高度(注意<UserControl>根元素上的Width 和 Height属性)。我们也可以完全去掉Width和Height属性,致使应用拥有动态的大小,自动地流式改变大小来适合包含它的HTML元素或浏览器窗口的大小。(我曾在这里的教程的结尾谈到过这个技巧)。如果我们要给我们的应用设置设计时的宽度和高度,我们可以在根UserControl元素上设置 d:DesignWidth="640" 和 d:DesignHeight="476" 属性。这会在使用设计器来设计应用时,致使设计器使用该尺寸的大小。
建造我们的聊天应用: 添加控件和颜色
至此,我们定义了我们的聊天应用的核心布局,让我们往里面加些控件,开始定制它的外观。
我们将先选择根Grid布局面板,定制它的背景颜色为渐变的蓝色(blue gradient)。可为我们所用,选择一个特定控件的一个简单的方法是使用“Interaction(交互)”面板,然后点击我们想选择的控件:
然后我们可以使用“"Brushes(画刷)”属性面板来定制一个蓝色的 LinearGradient 画刷为Grid的背景:
设置完成后,我们可以开始操作聊天窗口的底部,加一个“Send”(发送)按钮:
至于我们的聊天消息文本框,我们则将使用一个标准的文本框。但要加点活力,我们将先加一个RoundRadius为5的边框控件,然后加象这样的Background(背景)和BorderBrush(边框画刷):
然后我们在Border控件中嵌入我们的TextBox。
重要的小技巧: 为使用设计表面把TextBox嵌套在Border控件之中,我们需要在Interaction窗口中双击Border控件。这会将其设置成设计表面上的当前可插入控件,象下面这样用黄色高亮显示:
然后我们可以使用控件工具箱选择一个TextBox控件,将其加进Border控件。我们将设置TextBox的背景和边框画刷从父控件Border处继承其好看的曲线型外观:
Blend生成的XAML标识看上去象这样(注意,TextBox是内嵌在Border控件之中的,如果Border不是当前插入控件的话,是不会这样的):
我们也可以对header行重复上面的过程,将一个TextBox嵌入一个Border控件中,在右列里加一个图片控件,创建出象这样的UI:
由Blend生成的XAML标识会看上去象下面这样:
最后,绝对不是最不重要,我们将在中间一行添加另一个Border控件,往其中加一个ListBox控件。我们将配置Border控件延伸跨越Grid的两列,将它的背景和前景颜色进行定制。然后我们在ListBox加一些测试消息作为站位文字(我们将在后面对UI进行定制,并将其绑定到实际数值):
由Blend生成的XAML标识将看上去象下面这样:
至此,我们运行应用的话,我们会有一个在浏览器中运行的基本的聊天IM客户端(带硬写的值)。在我们改变浏览器大小时,应用会自动流动,改变大小以适合窗口:
我们还有一堆UI活要干,使我们的IM客户端看上去不至于很粗糙,但至少我们现在有东西可以运行了。
建造我们的聊天应用: 添加ChatMessage和ChatSession 2个类
至此,我们在Expression Blend中创建了初始的UI,让我们在 Visual Studio 中打开同个项目,加些我们可以绑定到UI的一些聊天类。
我们可以在 Visual Studio中选择 VS 2008 中的文件->打开项目,然后选择我们项目的项目文件来打开项目,或者在Expression Blend中我们可以右击项目节点,然后选“Edit in Visual Studio(在Visual Studio中编辑)”菜单项来启动打开了项目的VS 2008:
Beta1版本中的VS 2008的Silvelight支持包括对Silverlight 2方案的项目管理支持,完整的Intellisense和事件连接支持,以及对在Windows和Mac上运行的Silverlight应用的调试支持。VS 2008还支持对Silverlight .xaml文件的分割视图的编辑。譬如,下面是我们在Blend 建造的同个Page.xaml 文件,在VS2008中打开后的样子:
Beta1版的VS 2008设计视图并不是可交互的(意味着还是只读)。但你在源码视图中做的变动会马上在设计视图中更新,这给予你一个很好的XAML-pad的体验(在Silverlight 2 Beta1中,VS 2008支持完整的XAML源码intellisense)。
在这个博客贴子里,我们不会使用Visual Studio的XAML编辑器,而是将创建一些类,我们可以用来代表ChatSession以及相关的聊天消息。然后我们将使用Expression Blend将我们的UI控件绑定到这些类上。
我们先加一个定义了2个公开属性的叫“ChatMessage”的新类:
然后我们将创建一个叫“ChatSession”的类,它代表了一个聊天会话:
上面的ChatSession类有三个公开的属性,前2个属性代表远程聊天对象的用户名和avatar。
第三个属性是过去聊天消息的集合。注意,它的类型不是List<ChatMessage>集合,而是一个ObservableCollection<ChatMessage>集合。ObservableCollection对你来说,也许是个不熟悉的类型,假如你来自ASP.NET背景的话,但对那些来自Windows Forms或WPF背景的,大概会非常熟悉。基本上来说,这是个泛型集合类,往其中添加或去除条目时(或者其中的条目实现了INotifyPropertyChanged的话,在属性变动时),它会发出变化通知事件。这在做数据绑定时会非常方便,因为UI控件可以使用这些通知来知道自动刷新它们的值,而不用开发人员编写代码来显式地这么做。
ChatSession 还有2个公开的方法,其中一个方法的任务是连接到聊天服务器上去,另一个方法的任务是向聊天服务器发送消息。为简单起见(也因为我没有聊天服务器),我会对2个方法做假的实现。在实战中,我们大概会使用内置于Silverlight的网络socket实现连接到一个远程的聊天服务器上去。
ChatSession类实现了INotifyPropertyChanged接口,意味着它会呈示一个公开的PropertyChanged事件。在这个类中,我们会在改变它的属性时,触发这个事件。这会在属性值发生变化时,通知监听者(例如,与它数据绑定的控件),以允许它们重新绑定数据。
为设计时数据绑定实现假的数据
从纯粹功能性的角度来说,上面的代码是为实现我们的聊天客户端所需的所有的代码。但为帮着改进在Blend中的设计时体验,我们还将加一个构造器,检查我们是处于运行时模式还是设计模式,如果宿主于设计器里,那么就给ChatSession装载假的数据:
一会儿我们就会看到这是如何方便在设计器里呈现数据绑定之数据的。
建造我们的聊天应用: 在Expression Blend中使用数据绑定连接UI
既然我们定义了ChatMessage和ChatSession对象,我们可以在Expression Blend 中用它们来绑定到我们的UI控件了。
在我上个星期的《教程第五部分:用 ListBox 和 DataBinding 显示列表数据》 (木野狐译)中,我介绍了Silverlight和WPF中数据绑定的工作原理。在今天的贴子里,我们将使用Expression Blend 来连接数据绑定表达式,而不是手工输入这些表达式。我们将先使用Blend中Project面板下的"Data"面板:
我们将点击Data面板中的“+ CLR Object”链接,调出一个对话框,允许我们挑选任何.NET对象来数据绑定到我们的UI控件。我们将用它来选择我们刚创建的“ChatSession”对象:
这会把ChatSession对象加到我们的Data托盘上去,将它的属性(以及子属性)显示在一个树形视图里:
然后我们就可以在设计视图里通过选择Data托盘里的这些属性,把它们拖放到设计表面上的UI控件上,来绑定任意一个UI控件到这些属性上。例如,我们可以把RemoteUserName属性从Data托盘上拖拉到静态的"ScottGu"标签上,将它换成{Binding RemoteUserName} 数据绑定表达式:
当我们把“RemoteUserName”属性拖放到TextBlock上时,Blend会象上面那样问我们,是绑定这个属性到现有的TextBlock,还是创建一个新的控件来代表这个属性。如果我们选择默认的行为(绑定到现有的控件上),Blend就会询问我们想要的绑定表达式的类型:
我们表明我们要“OneWay(单程)”绑定到TextBlock的“Text”属性上去。当我们点击OK时,我们的控件的“Text”属性就会被更新为 {Binding RemoteUserName} 表达式。
我们可以重复这个拖放交互过程,把Image控件绑定到RemoteAvatarUrl 属性,也把 ListBox 绑定到MessageHistory集合属性上。完成之后,Blend就会象下面这样在设计视图表面中显示我们的伪数据:
你也许会对ListBox的内容感到疑惑,为什么条目都显示成了“ChatClient.ChatMessage”?那个么,目前ListBox是绑定到了自定义的.NET 对象的集合,“ChatClient.ChatMessage”字符串是调用ChatMessage实例的“ToString()”方法返回的值。
我们可以象这样,加一个<DataTemplate>到ListBox来修改它,让它好看些:
注: 在Blend 2.5 三月份的预览版中,你只能在源码视图中定义数据模板。在将来的预览版中,你将能够使用设计器来定义它们。这个功能已经在WPF中实现,如果你想试验一下的话。作为一个设计师,你可以交互式地创建数据的外观,完全的所见即所得的体验。去创建一个WPF项目试一下。
这么做的结果,会使得我们的UI在设计时看起来象下面这样:
在设计时显示这些“伪数据”的好处是,它允许我们对在运行时UI体验是什么样的会有一个比较好的感觉,允许设计师(或开发人员)轻松地设计UI,而不需要等待应用的其他部分的完成。
建造我们的聊天应用: 使用样式和控件模板更新我们的Button和ListBox的UI
在我的《第七部分:使用控件模板定制控件的观感 》Digg教程中谈到的一件事情是,关于Silverlight和WPF如何允许开发人员和设计师完全定制控件的观感(look and feel )的。这提供了巨大的灵活性来精雕细琢应用的UI,以创建恰如其愿的用户体验。
我们可以使用Silverlight和WPF的控件模板特性来定制我们上面聊天应用的Send按钮和ListBox结构,以构造稍微好看的观感。我们可以这么做,创建 "MessageHistory" 和 "SendButton" 样式资源,将之保存在项目的App.xaml文件中。每个样式对象可以有一个控件模板,修改了控件的观感和改变它的视觉结构。
注: 在Blend 2.5 三月份的预览版中,你只能在源码视图中定义数据模板。在将来的预览版中,你将能够使用设计器来定义它们。这个功能已经在WPF中实现,如果你想试验一下的话。作为一个设计师,你可以交互式地创建数据的外观,完全的所见即所得的体验。去创建一个WPF项目试一下。
例如,下面的ListBox控件模板可以用来去除ListBox控件周围的外圈双边框,定义一个只有列表容器卷动条的“平(flat)”的外观:
将这个模板施用到我们的ListBox上,将使得它显示出边缘周围平滑很多的样子:
我们可以用我们按钮的控件模板做得很花哨些,不光是定义一个自定义的按钮形状,还可以定义各种故事板动画来用于该形状,在它处于"MouseOver(悬浮)", "Pressed(按下)", 或"Normal(正常)"状态时, 提供自定义的UI行为(所有这些东西都可以封装在Style定义之中,意味着页面的开发人员不用做什么就可以启用这些东西):
在定义了"MessageHistory" 和"SendButton" 样式对象之后,很容易使用Expression Blend 将它们施用到设计表面的控件之上。
点击Expression Blend中的“Resources”工具窗口,它会列出我们项目中的所有资源地点:
我们可以展开“App.xaml”节点看其中我们可以使用的样式。要将一个特定样式施用到页面上的某个控件,我们只要将它拖放到该控件上就可以了。例如,这是在我们施用“SendButton”样式之前我们的发送按钮控件的样子:
将SendButton样式拖放到它之上,会将它改成使用我们自定义的控件模板形状/结构
因为我们的“SendButton”样式中定义了状态动画效果,按钮在运行时会随终端用户与之交互的方式的不同而变化。
在默认情形下,按钮看上去象这样:
当终端用户将鼠标移到按钮之上时,气球会微妙地变到比较淡的颜色:
在处于按下的状态时,按钮会陷下去,它的影子会消失:
在释放时,按钮又会冒起来。
这些微妙的动画和交互性姿态可以给应用增添一些色彩。最棒的是,设计师可以完全由他们自己建造和定制这些功能,实现页面功能的开发人员根本不用参与也不用编写任何代码,就可以启用这些功能。
在Expression Blend 2.5的将来的预览版中,设计师将不光能定义这个按钮的形状和结构,还能为它定义所有的动画过渡,全部使用设计表面(不需要编辑源码,也不用任何代码)。
实现我们的聊天功能
至此,我们使用Expression Blend对我们的控件UI做了数据绑定,还对UI的交互性做了修改和润色,让我们回到Visual Studio,来编写实现UI聊天行为功能的代码。
特别地,我们将向我们Page的构造器里添加下列代码,来开始与一个远程用户的ChatSession,然后处理“Send”按钮被点击,给远程用户发送一个消息时的场景:
在添加完上面的代码之后,重新运行我们的应用,我们将看到我们的UI现在数据绑定到了一个与RemoteUserName为"ScottGu" 的ChatSession(聊天会话),而不是我们早先定义的假的设计时数据。在消息文本框里输入文字,点击定制的Send按钮时,我们的ListBox会自动显示更新过的聊天历史:
你也许在疑惑为什么ListBox会自动更新?它这么做的原因是因为ListBox是数据绑定到ChatSession.MessageHistory属性上的,该属性的类型是ObservableCollection<ChatMessage>。这意味着,在一个新的 ChatMessage 对象添加进来时,该集合会自动触发变化通知事件,ListBox就会监测到这个事件,然后就会用新的数据更新本身。
不需要我们编写代码,就可以让ListBox对这些变化做反应。我们应用的干净的视图/模型绑定架构会自动为我们做处理。
结语
我只展示了Expression Blend支持的几个特性而已,所有这些特性在Silverlight和WPF项目中都工作的。所有这些功能都将在即将发布的Expression Blend 2.5三月份预览版中发布,不久这个预览版就可(免费)下载。
我想你会发现Visual Studio 2008 和 Expression Studio 会给建造出色的RIA解决方案带来巨大的生产力和威力。开发人员和设计师可以在开发相同项目时协作使用它们(而不用相互妨碍对方)。你还可以轻松地在一个机器上同时打开它们,用它们来同时编辑同一个应用。
在Expression Blend可以下载之后,我将在博客中对它做更多的讨论(以及我还没讨论过的其他一堆特性)。我还将在Silverlight 2 Beta1版发布之后,把上面的例程提供下载,这么你可以自己打开和运行其代码了。
希望本文对你有所帮助,
Scott