说明:本系列基本上是《WPF揭秘》的读书笔记。在结构安排与文章内容上参照《WPF揭秘》的编排,对内容进行了总结并加入一些个人理解。
Glyphs对象(WPF,Silverlight)
Glyphs对象可以同时用来创建有字体(或者说有固定字形)的文字内容与没有字体(没有定义固定字形,如Wingdings或Unicode)的文字内容。
注意,当在Silverlight环境中使用Glyphs对象时,由于字体文件会被下载到目标机器,所以作为开发人员需要确保有分发这个字体的权利。
Glyphs使用下面这些属性来控制文本内容,FontUri用来指定字体的位置。使用Indices或者UnicodeString属性来指定文字的内容,当使用Indices时可以使用一组分号分隔数字来定义文字间距等信息。FontRenderingEmSize属性用来定义文字的大小,使用StyleSimulations可以定义字体的样式,这个属性接受的值包括BoldSimulation、ItalicSimulation、BoldItalicSimulation或None。
下面的例子用来输出一段使用webdings字体的文本内容,webdings.ttf这个字体文件需要被放置在与Silvelight相同的文件夹中,以便可以分发到客户端,再次提醒你需要对所分发的字体拥有授权。
1 <Glyphs FontUri="webdings.ttf" Indices="133;134;135" Fill="Black" FontRenderingEmSize="48"/>
TextBlock(WPF, Silverlight)
这个对象的使用非常简单,用来展示一行或多行文字,与Glyphs不同,TextBlock使用内置支持的字体,如对于Silverlight默认支持如下9中字体:
-
Arial
-
Arial Black
-
Comic Sans MS
-
Courier New
-
Georgia
-
Lucida Grande/Lucida Sans Unicode
-
Times New Roman
-
Trebuchet MS
-
Verdana
使用TextBlock的FontFamily属性来设置字体,以上9种字体可以实现在任何系统浏览器环境下均可用,如果你指定了一个这9种之外的字体,运行时首先会在系统中查找这种字体如果找到则使用,反之将使用这9种中最接近的字体来代替。
FontSize属性用来定义字体的大小,FontStyle用来定义字体的样式,值可以是Normal或Italic。FontWeight属性用来定义字体的粗细,可接受的参数包括:Thin、ExtraLight、Light、Normal、Medium、SemiBold、Bold、ExtraBold、Black与ExtraBlack。TextDecoration属性用来确定文字是否使用下划线,接受的两个值为Underline和None。TextWrapping属性用来确定TextBlock中文字的换行方式,当设置为NoWrap时,文本内容会显示在一行里,而如果文本超出了TextBlock的宽度时内容会被截断。当设置为Wrap时,如果文本内容超过TextBlock的宽度时,会换到一个新行上。由于TextWrapping的不同设置会使内容或是被切断或是增加新行,从而影响到文本框的大小,这时可以使用TextBlock提供的ActualWidth与ActualHeight得到TextBlock的实际大小。
Runs标签
Runs标签用来改变TextBlock中文字的排版与样式,定义在TextBlock中的文本会使用TextBlock中定义的样式同样定义在Runs标签中的文本会使用Runs中定义的样式。通过下面的示例代码就可以很容易的明白:
1 <TextBlock FontFamily="Arial" Width="500" Text="Arial Text" Foreground="Pink" FontWeight="UltraBold"> 2 <Run Foreground="Blue" FontFamily="Comic Sans MS" FontSize="22"> 3 Comic Sans MS Larger 4 </Run> 5 <Run Foreground="Teal" FontFamily="Verdana" FontSize="12" FontStyle="Italic"> 6 Verdana Italic 7 </Run> 8 </TextBlock>
文字样式如下图:
可以看到文本的样式被分为3部分。
LineBreak行分割标签
LineBreak也很简单就是插入一个行分割符,我们把上面的例子改一下:
1 <TextBlock FontFamily="Arial" Width="500" Text="Arial Text" Foreground="Pink" FontWeight="UltraBold"> 2 <Run Foreground="Blue" FontFamily="Comic Sans MS" FontSize="22"> 3 Comic Sans MS Larger 4 </Run> 5 <LineBreak/> 6 <Run Foreground="Teal" FontFamily="Verdana" FontSize="12" FontStyle="Italic"> 7 Verdana Italic 8 </Run> 9 </TextBlock>
新的效果图:
很明显的第3段文字被转到一个新行中。
文档
这一部分我们重点介绍WPF的流文档,流文档用FlowDocument元素来表示,其中包含文本或其它内容,通过调整这些内容,流文档可以充分利用给定的空间。
提示:与WPF中的流文档不同,XPS属于固定布局文档,XPS在屏幕上看起来总是一致的。.NET Framework也包含创建与查看XPS的API,位于System.Windows.Xps和System.Windows.Documents命名空间下。
FlowDocument是一个FrameworkContentElement(FixedDocument也是),而FrameworkContentElement则是内容居中的FrameworkElement。FrameworkContentElement可以支持数据绑定,动画等WPF机制,但无法参与WPF布局。当FrameworkContentElement显示在屏幕中时最终会被放入FrameworkElement中。
TextElement用来表示可以放入FlowDocument的内容,这是一个抽象类,位于System.Windows.Documents命名空间下。下面着重介绍TextElement的一系列子类,及怎样将它们组合构建需要的FlowDocument。
两种最主要的TextElement分别是Block和Inline,它们都是TextElement的抽象子类。Block表示一个不可分割的矩形区域(跨页除外),Inline通常占据一个非矩形区域,从一行结尾到下一行开头。FlowDocument只支持Block作为其直接元素。FlowDocument提供一个BlocksCollection类型的Blocks属性作为内容属性,我们可以直接使用各种Block填充FlowContent。
Block
WPF提供了5种不同的Block
-
Paragraph
Paragraph中包含了需要放在FlowDocment的主要内容,Paragraph可包含一个Inline的集合。你会看到Paragraph中包含了一些文本但这些文本都位于一个名为Run的Inline元素中。
-
Section
用于将多个Block组合在一起,方便批量放置Block的Background或Foreground。
-
List
将ListItem元素的集合呈现为各种形式的列表。每个ListItem中可以包含一个Block元素,而这个Block元素通常为Paragraph。TextMarkerStyle类型的MarkStyle属性用于设置列表的样式,对于符号列表可设置为Box,Circle,Disc或Square,对于数字列表可设置为Decimal,LowerLatin,UpperLatin,LowerRoman和UpperRoman。设置为None表示一个普通列表。
-
Table
实现一个类似HTML Table的表格,每个单元格中可包含一个Block元素。
-
BlockUIContainer
用于将各种WPF元素,不管是Image,包含视频的MediaElement,Button或包含3D内容的Viewport3D放入一个FlowDocument中。
Inline
前文已经提到过Inline是用来填充Paragraph的元素,最常用的一种Inline元素为Run,该元素有一个StringText类型的属性,与一个接受字符串的构造函数,任何一个Inline的子元素都是一个Inline集合,所以Inline可以互相嵌套。几种不同的Inline如下:
-
Span
Span一般表示有特殊效果的文本,常见的几种Span为
-
Bold
-
Italic
-
Underline
-
Hyperlink
-
Anchored Block
AnchoredBlock抽象类有两个子类Figure和Floater,它们都是专门为包含Block而设计的。
-
Figure
Figure类似一个小型的FlowDocument,可以嵌入外部FlowDocument并且与外部FlowDocument是隔离的。外面的FlowDocument会将Figure包围在中间,Figure在FlowDocument中的位置可以通过其HorizontalAnchor和VerticalAnchor属性设置。这两个属性的默认值分别为ColumnRight和ParagraphTop。
-
Floater:
Floater是一种轻量的Figure,其设有HorizontalAnchor和VerticalAnchor两个属性,取而代之是一个简单的HorizontalAlignment属性,其有Left,Center,Right或Stretch四个属性值。
-
-
LineBreak
这个作用很好理解,就是换行。
提示:添加换页符的方法是,设置后一页Paragraph(包括Sectioin,List等)的BreakPageBefore属性为true。
-
InlineUIContainer
其除了不能放在Paragraph的最后外,其余特性与BlockUIContainer几乎完全一致。
FlowDocument的读写
如果我们需要编辑一个FlowDocument,可以将其放在一个RichTextBox中,也可以将RichTextBox的IsReadOnly设为true。防止用户编辑。
WPF另外提供了三种专门用于显示FlowDocument供阅读的控件。
- FlowDocumentScrollViewer:将文档显示在一个带有滚动条的连续文件,类似于在IE中浏览网页的效果。需要将IsToolBarVisible设为true来启用缩放。
- FlowDocumentPageViewer:会把文档分成一个个页,该模式类似Word中的"全屏阅读"模式。
- FlowDocumentReader:这是XAML中的FlowDocument默认使用的控件,其内置了FlowDocumentScrollViewer和FlowDocumentPageViewer两个控件,并内建文本搜索等额外功能,默认支持缩放。
使用注释
前文介绍的WPF提供了三个FlowDocument阅读控件都支持注释的显式与添加,支持这个功能的为System.Windows.Annotations命名空间下的AmotationService类,该类提供了5个与注释有关的命令。
-
CreateTextStickyNoteCommand:在选中的文本上附加一个新的基于文本的StickyNoteControl作为注释。
-
CreateInkStickyNoteCommand:在选中的文本上附加一个新的基于墨水的StickyNoteControl作为注释。
-
DeleteStickyNoteCommand:删除选中的一个或多个StickyNoteControl。
-
CreateHighlightCommand:用传入的命令突出显示选中的文本。
-
ClearHighlightsCommand:从选中的文本中移除所有突出显示的内容。
另外,我们还需要自己添加控件,并将控件与上述 Command关联起来控制FlowDocument中的注释。WPF会自动根据上下文启用或禁用我们添加的控件。下面的XAML展示了上述控件的定义:
1 <Window 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:a="clr-namespace:System.Windows.Annotations;assembly=PresentationFramework" 5 x:Class="Window1" Initialized="OnInitialized" Closed="OnClosed"> 6 <Canvas> 7 <StackPanel Orientation="Horizontal"> 8 <Button Command="a:AnnotationService.CreateTextStickyNoteCommand" CommandTarget="{Binding ElementName=reader}"> 9 Create Text Note 10 </Button> 11 <Button Command="a:AnnotationService.CreateInkStickyNoteCommand" CommandTarget="{Binding ElementName=reader}"> 12 Create Ink Note 13 </Button> 14 <Button Command="a:AnnotationService.DeleteStickyNotesCommand" CommandTarget="{Binding ElementName=reader}"> 15 Remove Note 16 </Button> 17 <Button Command="a:AnnotationService.CreateHighlightCommand" CommandTarget="{Binding ElementName=reader}"> 18 Create Yellow Highlight 19 </Button> 20 <Button Command="a:AnnotationService.ClearHighlightsCommand" CommandTarget="{Binding ElementName=reader}"> 21 Remove Highlight 22 </Button> 23 </StackPanel> 24 25 <FlowDocumentReader x:Name="reader"> 26 <FlowDocument> 27 </FlowDocument> 28 </FlowDocumentReader> 29 </Canvas> 30 </Window>
下面的C#代码展示上述XAML中使用的OnInitialized和OnCloseed方法:
1 Stream stream; 2 3 protected void OnInitialized(object sender, EventArgs e) 4 { 5 // Enable and load annotations 6 AnnotationService service = AnnotationService.GetService(reader); 7 if (service == null) 8 { 9 stream = new FileStream("storage.xml", FileMode.OpenOrCreate); 10 service = new AnnotationService(reader); 11 AnnotationStore store = new XmlStreamStore(stream); 12 service.Enable(store); 13 } 14 } 15 16 protected void OnClosed(object sender, EventArgs e) 17 { 18 // Disable and save annotations 19 AnnotationService service = AnnotationService.GetService(reader); 20 if (service != null && service.IsEnabled) 21 { 22 service.Store.Flush(); 23 service.Disable(); 24 stream.Close(); 25 } 26 }
这些代码主要完成了AnnotationService的启用与禁用,加载与保存注释文件(xml)。
提示:如果感觉StickyNoteControl默认的外观不是你想要的,可以通过自定义模板来改变其样式。
本文完
参考:
《WPF揭秘》