【翻译】Pro.Silverlight.5.in.CSharp.4th.Edition - 第五章 元素 01
目录:点击这里
上一篇:【翻译】Pro.Silverlight.5.in.CSharp.4th.Edition - 第四章 依赖属性和路由事件 03
到现在为止我们已经完成了XAML、布局以及鼠标键盘事件处理的基本原理的学习,现在我们可以研究一下用来创建各种用户界面的元素了。
本章中,我们会大概了解Silverlight的核心元素,其中很多都是我们尚未接触过的。首先,我们会学到如何展示元素的包裹效果、TextBlock中的格式化文本以及如何用Image元素来展示图片。接下来,我们会学习内容控件(content control),其中包括Silverlight中的各种风格的按钮和ToolTip(提示框)控件。最后,我们会认识一些专业性更强的元素,比如Silverlight的列表、文本输入、范围和日历等控件。在学习完本章后,我们会这些构建出Silverlight页面的基本组成元素有一个立体的认识。
新版变化:Silverlight 5 新增加了两个基于RichTextBox的特殊控件:RichTextBlock和 RichTextBlockOverflow。使用这些控件,我们就可以只通过较少的工作量就可以将文本内容用多列的方式来显示,并且可以实现文本和图片环绕在一起的效果。在“富文本块(RichTextBlock)”这一章节中我们会详细讲述这方面内容。
Silverlight元素
我们已经见过不少Silverlight的核心元素,比如第3章中的布局容器。还有一些专业性更强的元素,比如用于绘制2D图像、用于展示深度缩放图片已经用于播放视频的那些元素会在本书的后面几章才讲到。本章主要讲解的Silverlight中的那些基本元素,比如按钮,文本输入框,下拉列表和复选框等等。
表5-1概括了Silverlight中的关键元素并且标明了其对应的章节。这个清单是按照VS中工具箱中的元素的字母顺序排列的。
表5-1 Silverlight中的元素
类 |
说明 |
在本书中的位置 |
程序集(如果不是核心元素) |
AutoCompleteBox |
一个特殊的文本输入框,当户用在输入内容的时候会提供一个可能匹配的列表内容。 |
本章 |
System.Windows.Controls.Input.dll |
Border |
一个单一元素的矩形或者圆角的边框。 |
第3章 |
|
Button |
一种普通的按钮,默认有一个灰色阴影的背景,用户点击按钮后启动某个任务。 |
本章 |
|
Calendar |
一次只显示一个月的日历控件,可以用来让用户选择一个日期。 |
本章 |
System.Windows.Controls.dll |
Canvas |
一种使用精确坐标来给元素布局的布局容器。 |
第3章 |
|
CheckBox |
一个可以被选中或者补选中的方框,旁边辅之以可选的说明内容。 |
本章 |
|
ComboBox |
一个下拉列表框,下拉选项只有一个可以被选上。 |
本章 |
|
ContentControl |
被所有其它内容控件(比如Button、CheckBox、ToolTip、ScrollViewer等等很多)继承的基础控件;尽管可以直接使用这个控件,不过我们大多数情况下都会选择用它的子控件。 |
本章 |
|
DataGrid |
一个用于在多列网络中展示数据对象集合的富数据控件,提供内建特性比如分类和选择。 |
第21章 |
System.Windows.Controls.Data.dll |
DataPager |
给数据源提供翻页功能的数据控件,可以和DataGrid这样的控件协同工作。 |
第21章 |
System.Windows.Controls.Data.dll |
DatePicker |
一个输入日期的文本输入框,带有一个下拉式的日历便于日期选择。 |
本章 |
System.Windows.Controls.dll |
Ellipse |
椭圆形。 |
第8章 |
|
Frame |
一种用于在普通页面中显示一个单独XAML文件的容器。它可以用于创建复杂的页面导航系统。 |
第7章 |
System.Windows.Controls.Navigation.dll |
Grid |
将子元素放置在不可见网格的单元格中的布局容器。 |
第3章 |
|
GridSplitter |
可以用于调节Grid的行高和列宽的一个可以移动的条。 |
第3章 |
System.Windows.Controls.dll |
HyperlinkButton |
一个可以让用户直接跳转另一个网页的链接。 |
本章 |
|
Image |
一个显示图片的元素。 |
本章 |
|
Label |
一个文本显示控件。它和TextBlock类似,但是比TextBlock要显得重量级一些。当处理数据绑定控件的时候,Label可以检查数据绑定对象,提取出标题文本并且检查是否该显示字段指示器或者错误指示器 |
第21章 |
System.Windows.Controls.dll |
ListBox |
多个选项的列表,这些选项中只有可以被选中。 |
本章 |
|
MediaElement |
媒体文件,比如视屏窗体。 |
第12章 |
|
MultiScaleImage |
一个支持Silverlight的深度缩放(DeepZoom)特性的元素,可以让用户能够在一个非常大的图上精确定位某一点上。 |
第12章 |
|
PasswordBox |
密码框,用户输入的内容会被掩饰成其他字符串。 |
本章 |
|
ProgressBar |
一个用来指示所指定的任务完成进度的着色进度条。 |
本章 |
|
RadioButton |
一组选择项中能够提供一个单一选择的单选框,选项内容位于小圆圈旁边。 |
本章 |
|
Rectangle |
长方形元素。 |
第8章 |
|
RichTextBox |
富文本输入框,支持各种格式的内容输入。 |
本章 |
|
ScrollViewer |
滚动条,此容器用于尺寸较大内容的展示。 |
第3章 |
|
Slider |
滑动条,可以让用户通过拖动滑块的方式来设置一个数值。 |
本章 |
|
StackPanel |
将子元素按照从上到下或者从左到右的方式排列的布局容器。 |
第3章 |
|
TabControl |
选项卡容器,将元素通过选项卡分开展示,可以让用户分别查看每个选项卡的内容 |
本章 |
System.Windows.Controls.dll |
TextBlock |
一个通用的文本显示控件,可以让多种内联的文本片段具有不同的格式 |
本章 |
|
TextBox |
我们最常见到的文本输入控件 |
本章 |
|
TreeView |
一种以树形结构展示项目的富数据控件,树形结构的层数没有限制 |
第21章 |
System.Windows.Controls.dll |
Viewbox |
一种可以对其内部元素进行缩放的容器 |
第3章 |
|
WebBrowser |
Silverlight应用程序OOBM模式下内嵌的浏览器控件 |
第18章 |
|
在第1章中,我们了解到:Silverlight应用程序如果引用了一些非核心的控件,那么这些控件会自动被编译进XAP文件中,这样在程序部署的时候无须多余设置就包含了这些控件。正如在表5-1的最后一列所看到的,非核心控件还是占少数,即使是像MultiScaleImage这种特殊性很强控件也属于标准Silverlight控件包的一部分。
在本章接下来的内容中,我们会对表5-1中的部分控件进行仔细分析,在那之后,我们就了解了如何在应用程序中自定义这些控件。
提示:如果你还想了解更多其它的控件,可以在Silverlight Toolkit中找到许多功能犀利而且样子华丽的控件(在微软的开源站点CodePlex上可以免费下载,地址是http://silverlight.codeplex.com)。丰富而且漂亮的图表控件是其亮点之一,这个图表控件包含了饼图到散点图——几乎所有你能在Excel中找到的图表。安装了Silverlight Toolkit之后,我们会在Silverlight的工具箱中发现那些新的控件。
静态文本
Silverlight中包含了Label控件,不过这个控件是用于数据绑定这种情况,我们将在第21章中讨论它。显示格式化文本块最好的方式是用轻量级而且灵活性高的TextBlock元素,我们在前面四个章节中已经看到很多用到了TextBlock的示例了。
TextBlock元素的用法非常直截了当:它的Text属性值就是我们要展现的出来的字符串内容。
<TextBlock Text="This is the content."></TextBlock>
或者我们可以将这段文本作为内嵌内容:
<TextBlock>This is the content.</TextBlock>
这种方式的最主要优点是可以增加换行符和制表符,这样可以让代码中的大段文本的可读性更高。Silverlight遵循XML的标准规则,这意味着空格会被压缩(collapse)。因此,多个空格、制表符和回车这些都会被替换成单个空格。
将文本在确定的位置分成多行的方法有三种。第一种是使用多个TextBlock元素;第二种是TextBlock中使用LineBreak,如下所示:
<TextBlock> This is line 1.<LineBreak/> This is line 2. </TextBlock>
第三种方式是在TextBlock元素上加上属性xml:space="preserve",这就会告诉XAML解析器对起始标签的结束符号“>”和结束标签的起始符号“<”之间的所有空格、制表符和回车都如实解析。示例如下:
<TextBlock xml:space="preserve"
>This is line 1. This is an indented line 2.</TextBlock>
这种方式可以做到对文本块的格式进行任何细微的调整。不过由于细节内容太严格,它对于实际应用程序来说不太适用。
备注:使用内联文本的时候,不可以使用“<”、“>”这两个符号,因为它们属于XML中的特殊字符。我们需要使用“<”(less than)和“>”(great than)来分别代替“<”、“>”这两个尖角括号。
意料之中,默认情况下文本的颜色是黑色。我们可以使用Foreground属性改变文本的颜色。我们可以在XAML中用如下方式来进行颜色设置:
<TextBlock x:Name="txt" Text="Hello World" Foreground="Red"></TextBlock>
或者在代码中用:
txt.Foreground = new SolidColorBrush(Colors.Red);
我们也可以用RGB值来代替颜色名称。另外,我们还可以使用半透明的颜色,这样可以让背景透过展示出来。这些内容我们已经在第3章中关于如何给面板加上一个背景这个话题中讨论过了。
提示:一般我们使用纯色作为文本的颜色。(默认的就是一个黑色笔刷。)不过,我们还可以实现一些更独特的效果:比如用渐变色或者图像拼贴等花哨的笔刷(详见第9章)。
另外,TextBlock还提供了TextAlignment属性(用于改变文本的对齐方式)、Padding属性(用于设置文本和TextBlock外边缘的边距)以及其它一些用于设置字体、内联格式、文本换行、文本去空白的属性。接下来的章节会逐一讨论这些属性。
字体属性
TextBlock类中定义了各种决定控件中文本显示方式的属性,具体见表5-2。
表5-2 Control类中的字体相关的属性
名称 |
说明 |
FontFamily |
字体名称。由于Silverlight是一种客户端技术,它只支持9中内置的字体(Arial、Arial Black、Comic Sans MS、Courier New,Georgia、Lucida、Times New Roman、Trebuchet MS和Verdana)。不过,我们可以通过一些操作将其他字体打包进项目的程序集中便可以使用定制的字体了(很快我们会在“字体嵌入”章节中学习这个技巧)。 |
FontSize |
字体的像素(pixel)大小。普通Windows应用程序使用点(points)来作为度量值——大小为标准PC显示器中1英寸的1/72;而1像素的大小则是1英寸的1/96。因此,如果想将Silverlight字体大小转换常见的点计算方式,只需要将值乘以3/4即可。比如,20像素的字体大小和15点的字体大小一样。 |
FontStyle |
字体样式,其值为一个FontStyle对象。使用 FontStyles 类的静态属性 提供 FontStyle 值,包括Normal和Italic这两种。使用Italic则字体以倾斜效果呈现。不过这种行为只是大致类似斜体字效果,而不是真正的斜体字。 |
FontWeight |
设置字体的粗细程度,其值为一个FontWeight对象。使用 FontWeights类的静态属性 提供 FontWeight值。Normal和Bold这两个是最常用的,有些字体还提供了其他一些选择:Bold、Light、ExtraBold等等。如果使用Bold,那么Silverlight会在字的轮廓上绘制一个稍厚的边框,这样就模拟了一个粗体字的效果。 |
FontStretch |
文本字之间拉伸或者压缩的程度,其值为一个FontStretch对象。使用 FontStretchs类的静态属性 提供 FontStretch值。比如,UltraCondensed使文本宽度减少一半,UltraExpanded则使文本宽度增加一倍。字体伸缩是一种OpenType特性,并不是所有的字体都支持。Silverlight内置的字体不支持这种变形特性,因此这个属性只在自定义字体中才有效果。 |
当然,这些属性中最重要的还是FontFamily。它是关联的字体的一个集合——比如,Arial Regular、Arial Bold、Arial Italic和Arial Bold Italic都属于Arial字体家族的一部分。尽管每个变量的排版规则和特性都是单独定义的,不过操作系统会识别出它们是相关联的。因此,我们可以将元素的字体设置为Arial Regular,FontWeight属性设置为Bold——然后Silverlight就会自然将字体转换为Arial Bold。
选择字体的时候,比如设置为字体的完整名称,如下所示:
<TextBlock x:Name="txt" FontFamily="Times New Roman" FontSize="18"> Some Text</TextBlock>
对应的等效代码如下:
txt.FontFamily = "Times New Roman"; txt.FontSize = "18";
简短的字符不足以用来识别出FontFamily。这就意味着我们不能简单地使用Times或者Times New来代替Times New Roman这个完整名称。
我们可以使用字体的完整名称来得到斜体或者粗体效果,这是一种可选择性的做法。如下所示:
<TextBlock FontFamily="Times New Roman Bold">Some Text</TextBlock >
不过,更简洁明了、更灵活的方式还是FontFamily属性和其他属性(比如FontStyle、FontWeight)分开处理。比如,下面的这段XAML标记就是将FontFamily设置为Times New Roman,将FontWeight设置为FontWeights.Blod:
<TextBlock FontFamily="Times New Roman" FontWeight="Bold">Some Text</TextBlock >
标准字体
Silverlight提供了9个内置的核心字体,这可以保证程序内容能够准确地在各种支持Silverlight的浏览器和操作系统上呈现出来。如图5-1所示。
图5-1 Silverlight的内置字体
图中所示的Lucida有两个名称稍有不同的种类。Lucida Sans Unicode是Windows中的,而Lucida Grande则是Mac OS X中的,这两个本质是一样的。FontFamily属性支持字体选择倒回以保证这种机制可以正常运行——换句话说,我们可以将多种字体用逗号分开,那么Silverlight会选用客户端PC第一个支持的字体。默认的TextBlock字体其实就相当于设置了FontFamily属性为字符串“Lucida Sans Unicode, Lucida Grande.”。
可能你会想:我可以更多的特定字体,不管客户端电脑是否提供这些字体。然而,Silverlight不允许这样做。如果我们设置了一个字体既不是Silverlight内置的9种字体之一,也不是应用程序集中已嵌入(后续将会讲到)的字体,那Silverlight就会忽略这个字体,这和客户端电脑是否安装了对应的字体没有关系。这样设计是有它的道理的——毕竟,如果使用了只在某些机器上支持的字体,这会导致应用程序在其他客户端上显得凌乱、不可读,而这种错是很容易犯的。
字体嵌入
如果我们想在应用程序中使用一个非标准的字体,我们可以将这个字体嵌入到应用程序的程序集中。这样就不会出现找不到我们所需要的字体的问题了。
嵌入操作的过程很简单。首先,将字体文件(典型的字体文件都是以.ttf作为扩展名)添加到应用程序中,并且将Build Action设置为Resource。做法就是在VS的资源管理器中选择这个字体文件,然后再属性页面中修改Build Action设置。
下一步,在设置FontFamily属性的时候,我们要按照如下格式处理:
字体文件名称#字体名称
比如说,如果我们选择的字体文件的名称是BayernFont.ttf,它包含的字体名称为Bayern,那么我们对应的标记就是这样的:
<TextBlock FontFamily="BayernFont.ttf#Bayern">This is an embedded font</TextBlock>
如图5-2是最终运行效果。
图5-2 使用嵌入字体
另一种方式是我们可以使用包含了这个字体文件的流来设置字体。这种情况下,我们需要设置用字体文件的流来设置TextBlock.FontSource属性,然后再用相应的字体名称来设置TextBlock.Family属性。比如说如果我们将BayernFont.ttf文件作为一个项目(假定项目名称是“FontTest”)的一个资源,我们可以用如下代码来实现字体的设置:
StreamResourceInfo sri = Application.GetResourceStream( new Uri("FontTest;component/BayernFont.ttf", UriKind.Relative)); lbl.FontSource = new FontSource(sri.Stream); lbl.FontFamily = new FontFamily("Bayern");
为了能从正确的当前程序集中找出对应的资源,代码中使用了Application.GetResourceStream()方法,URL参数使用了如下这样特殊的语法:
程序集名称;component/字体资源名称
不管使用哪种方式,使用自定义字体的过程还算是比较简单的。然而,字体嵌入涉及到许可问题。大多数字体的提供商允许他们的字体嵌在文档(比如PDF)中,但是不能在程序中(比如Silverlight程序集)。原因很明显:用户可以手动下载XAP文件,解压缩之后便可以获取字体文件然后在其个人电脑上是使用。Silverlight在字体许可问题上没有做强制手段,不过你在使用某个字体之前务必保证是在法律许可的前提下。
我们可以微软的免费字体属性扩展功能来检查字体的嵌入许可权限(详见www.microsoft.com/typography/TrueTypeProperty21.mspx)。安装后,在字体文件上点击右键,选择属性就可以看它的完整细节信息。选择Embedding标签就可以看到这个字体的嵌入许可信息。如果标有“Installed Embedding Allowed”则表示适用于Silverlight应用程序,而标有“Editable Embedding Allowed”则可能不适用。这种情况下就得和字体提供商进行协商了。
备注:如果所有的尝试都失败了,我们还可以将字体转为图形来回避许可问题。这种技巧适用小段图形文本(比如标题),不适用于大段文本。我们可以将图像文本存为位图,或者用Silverlight的Path元素将文本转为一系列形状(这种技巧将在第8章中讨论)。我们可以用Expression Designer或者Expression Blend将图形文本转为路径(操作方式是选上TextBlock后,在菜单栏依次选择Object→Path→Convert to Path)。有趣的是,Silverlight也可以让我们通过代码实现这种技巧。http://tinyurl.com/69f74v展示的例子是就是调用一个将非西方文本动态转为路径的web服务。这个web服务的返回值就是可以在Silverlight中无缝展现的路径数据。
下划线
我们可以通过将TextDecorations属性设置为Underline来给字加上下划线:
<TextBlock TextDecorations="Underline">Underlined text</TextBlock>
在WPF中有几种文本装饰的类型,包括上划线和删除线。不过目前Silverlight中只支持下划线。
如果想给一个文本块中的某个单词单独加上下划线,就需要使用内联元素,下一小节就会说到。
Run对象
在很多情况下,我们可以希望能够多个格式迥异的小段文本组合在一起放在一个TextBlock中。想实现这个效果,我们需要在TextBlock中使用Run对象。下面这段示例代码就是将各个词语用不同的格式来呈现(运行效果如图5-3):
<TextBlock FontFamily="Georgia" FontSize="20" > This <Run FontStyle="Italic" Foreground="YellowGreen">is</Run> a <Run FontFamily="Comic Sans MS" Foreground="Red" FontSize="40">test.</Run> </TextBlock>
图5-3 使用多个Run对象实现文本的格式化
Run对象中所支持的关键格式化属性和TextBlock一样,包括Foreground、TextDecorations和那5个字体属性(FontFamily、FontSize、FontStyle、FontWeight和FontStretch)。
从技术的角度来说,Run对象并不是真正的元素。它其实是个内联(inline)标签。Silverlight提供了两种内联标签——前面所介绍过的LineBreak类和现在看到的Run类。我们可以通过TextBlock.Inlines这个集合来读取TextBlock里的Run对象。实际上,TextBlock有两种重叠的内容模型。我们可以直接Text属性来设置文本,也可以通过Inlines集合来处理显示的文本内容。不过,任何一种方式的操作都会影响到另一种方式,也就是说如果我们之后设置了TextBlock的Text属性,那么之前这个TextBlock的内联集合数据就都抹掉了。
备注:内联标签Run和LineBreak都属于文本元素模型的一部分,也用于本章后面要讲到的RichTextBox控件,而且功能更完整。
包装文本
要想将文本分为几行,就要使用TextWrapping属性。一般情况下,TextWrapping的值是TextWrapping.NoWrap,如果文本的内容超出了容器元素的右边界就会截去掉相应的超出部分内容。如果将TextWrapping的值设置为TextWrapping.Wrap,那么文本内容就会在TextBlock的宽度因为某些情况不够长的时候被分为多行。(比如当TextBlock在一个比例分配或者固定宽度的Grid单元格中的时候。)当进行包装处理的时候,TextBlock会在最接近宽度的空白处换行。如果出现单词(字)的长度超出了当前行的可用宽度,那么TextBlock就会从能使它全部显示出来的位置进行这个单词(字)的字符串分离。
文本换行的时候,LineHeight和LineStackingStrategy属性起很关键的作用。LineHeight属性可以设置成为每行都是用的一个固定高度(像素)。然而,LineHeight只能用于增加行的高度——如果设置的高度小于本行显示文本所实际需要的高度,那么LineHeight的设置就会被忽略。
LineStackingStrategy决定了TextBlock如何去处理使用不同字体的多行内容。我们可以选择使用标准的行为:MaxHeight,会行高设置为本行的最高的文本块的高度;BlockLineHeight,则会将每行都设置为一个固定高度——来自LineHeight属性,这样高度小的文本会有额外的空白空间,而超出高度的文本则会覆盖到其他行上。如图5-4展示了这两种不同方式的运行效果:
图5-4 两种不同的计算行高的方式
TextBlock将文本包装在一个简单的矩形区域中,目前不可能让文本内容照着曲线或者形状的轮廓来包装。不过,我们可以使用本章后面将会讲到的RichTextBox的溢出特性来实现这些的需求效果。
去除文本空白
通过前面我们已经知道,文本如果不适合它的容器的宽度,那么最后有两种可能的结果:换行或者被截断了。比如说“Silverlight is a fantastic platform”这个句子,它可能被截取成如下的展现方式:
Silverlight is a fant
TextTrimming属性可以用来以一种更有好合理的方式来处理这样的问题。如果将TextTrimming属性的设置为WordEllipsis(也是除默认之外的唯一一个选择项),Silverlight会在截取后的文本上后面增加一个省略号。这样,之前的示例最终的运行结果会如下所示:
Silverlight is a ...
这就会给用户一个视觉上的提醒,告诉用户还有完整的文本内容没有显示出来。
字符间距
如果觉得输入的字符串显得有点拥挤,我们可以使用LineHeight属性增加行之间垂直方向的间距(前面已经有所介绍),另外,我们还可以使用CharacterSpacing属性增加同一行内的字符之间水平方向的间距。如下所示:
<TextBlock FontSize="20" CharacterSpacing="100"> These letters are spaced out. </TextBlock>
CharacterSpacing属性的单位值是当前字体大小的1/1000。因此,上例中CharacterSpacing属性值为100,而字体大小是20,最终计算后字间距为2像素(100/1000×20=2)。
转载于:https://www.cnblogs.com/xtechnet/archive/2012/09/14/Silverlight5_Chapter05_Part01.html