DotNet关键知识点——WPF篇(四)
1. 资源和Pack URI体系
MSDN上比较完整的介绍:
http://msdn.microsoft.com/en-us/library/aa970069.aspx
使用Pack URI的资源必须以Build Action为Resource(不是工程属性中资源列表里的Embedded Resource,其机制更复杂)加入WPF工程,嵌入程序二进制文件中的资源更新时要重新生成工程。
Pack URI基本格式:pack://<authority>/<path>
其中授权方<authority>对应一个包(package),路径<path>对应一个部件(part)。两者类似于应用程序和它相关的诸文件的关系。
WPF支持两个授权方:application:///和siteOfOrigin:///
Pack URI使用中必须遵循RFC 2396,上述'/'要替换成',','%'和'?'等要转义。
通常使用的授权方是application:///;路径为资源在工程目录中的相对位置,具体格式:
本代码:Path
引用代码:AssemblyShortName[;Version][;PublicKey];component/Path
注意:引用代码不能使用siteOfOrigin授权。HTML不能任意访问,Pack URI体系只允许通过siteOfOrigin授权方路径访问HTML资源。
以上的URI格式可以直接代入Uri对象的构造函数。
手动获取资源(仍是嵌入程序的资源):通过Application.GetResourceStream(uri)方法获得System.Windows.Resources.StreamResourceInfo,从其UnmanagedMemoryStream属性指定的流中读取内容。可以应对某些不支持Pack URI的场合(如Label的Content)。
内容文件(不是资源):对不支持Pack URI而源需要频繁更新的场合(如MediaElement的Source),可将文件以Build Action为Content加入工程,并将Copy To Output Directory设置为Copy Always(保证每次生成将源原封不动复制到适当的路径),然后用相对路径作为源。
松链接文件(不是嵌入程序的资源):用siteOfOrigin:///授权方指定的路径中的文件,则从该指定位置读取资源,这样每次资源更新不必重新生成工程。siteOfOrigin:///对full-trust的桌面程序为程序的运行根目录;对full-trust的ClickOnce部署程序为部署路径;对partial-trust的ClickOnce部署程序或XBAP程序为程序的宿主路径。松链接文件一般也用类似内容文件的方法接入工程。
Image的Source访问:在代码中需要用image.Source = new BitmapImage(new Uri(…))进行,支持Pack URI。
Bitmap元数据访问:BitmapDecoder decoder = BitmapDecoder.Create(uri, …); ((BitmapMetadata)decoder.Frames[0].Metadata).XXX获取元数据属性。
2. 逻辑资源Logical Resources
逻辑资源不属于视图树,可以加在XAML几乎任何位置(单元甚至Application的Resources属性),包含任何对象,用x:key标识命名,并被下级单元引用。
静态逻辑资源引用:XXX="{StaticResource 命名}";动态的则用DynamicResource。两者区别是是否更新访问以反映资源对象引用(不是内容)的变化。
逻辑资源库ResourceDictionary,其MergedDictionaries属性是一个Collection<ResourceDictionary>类型,因此能够装载多个别的ResourceDictionary;ResourceDictionary的Source属性可以指定引入某个XAML文件中的资源。因为ResourceDictionary是一个资源集合,本身有Add方法,实现IDictionary等接口,因此在其中添加普通资源和MergedDictionaries并行不悖。
当由于ResourceDictionary和别的资源一同加入一个Resource时,ResourceDictionary必须也用x:Key命名(否则运行期异常),这样会导致ResourceDictionary中的资源无法直接访问。
ResourceDictionary FrameworkElement.Resources,因此每个WPF单元都能定义逻辑资源,且能被逻辑树上后续单元访问。
3. 文档
主要相关类型的继承关系:
DependencyObject
- ConentElement – FrameworkContentElement – FlowDocument
- TextElement – Block – Paragraph
- List
- Table
- Section
- BlockUIContainer
- Inline – Run
- Span – Bold
- Italic
- Underline
- Hyperlink
- LineBreak
- AnchoredBlock – Floater
- Figure
- InlineUIContainer
- TableRowGroup, TableRow, TableCell
- ListItem
- Visual – UIElement – FramworkElement - Control – FlowDocumentScrollViewer
- FlowDocumentReader
- DocumentViewerBase – FlowDocumentPageViewer
- DocumentViewer
类别 类型 说明 流式文档浏览器 FlowDocumentScrollViewer Document属性指向FlowDocument,仅在IsToolBarVisible设置为"True"开启缩放界面,缩放值Zoom=”100”为本身大小,可设MinZoom和MaxZoom规定缩放范围。 FlowDocumentPageViewer 其(DocumentViewerBase.)Document属性指向FlowDocument,提供根据自身大小自动分页,也浏览和缩放等功能。 FlowDocumentReader Document属性指向FlowDocument,可以包括上述两种的不同模式浏览。 流式文档 FlowDocument Blocks属性可包含多个Block对象 文本单元 TextElement 抽象类,包含了文档块和文档条目共有的内容。主要是前背景、字体等,作用域为所包含的内容。 文档块(Block) Block 通常是比较独立的文本 Paragraph 属性包括边界、行距、文本对齐、边框属性等。
用Inlines可获取其中嵌入的文档条目。Paragraph间换行。List/ListItem 用于列举,MarkerStyle用于指示标记。
ListItem的Blocks包含多个Block对象。Table / TableRowGroup
/ TableRow / TableCellTable.RowGroups可包含若干个TableRowGroup,但通常只需一个。TableRowGroup.Rows含若干个TableRow,TableRow.Cells含若干个Cell。TableCell.Blocks指向内容。 Section 主要用于对包含内容安排统一的样式。 BlockUIContainer 以块形式在文档中加UI。 文档条目(Inline) Inline 较Block小,和周围关联度更大的文本单元 Run 即通常的文本,默认的文本包装器。 Bold, Italic, Underline 指示一段指定格式的文本。 Hyperlink 用NaviateUri指定浏览对象,基于网页的程序可以是其他Page或网页等。也可用与激发命令(Command属性)或事件。 LineeBreak 换行 Span 用于包装多个条目(Span.Inlines),赋予相同的样式。 Floater AnchoredBlock.Blocks包含多个块。用HorizontalAlignment指定其内容游离于周边文字。 Figure 类似Floater,控制更丰富。文档必须支持分页。 InlineUIContainer 以条目形式加入UI。
间隔保持:默认情况下,内容文本中所有间隔(包括空给、换行、制表符等)在实际运行显示时一律转换为一个空格,当将xml:space=”preserve”应用于流动文本对象时,所有间隔保持。
打印:
所有上述文档浏览器均支持Print()方法,打开标准的打印对话框界面。
也能通过激发ApplicationCommands.Print(可以用ApplicationCommands.Print.Execute(null, flowdoc)打印文档),或在文档激活时按Ctrl+P实现打印。
用PrintDialog:bool? printDlg.ShowDialog()方法,返回true时,(1)用printDlg.PrintVisual(visual, “comment”)完成对Visual对象visual的打印(视图打印和文档打印结果不同);或(2)用printDlg.PrintDocument(documentPaginator, “Comment”)完成对文档打印,其中documentPaginator = ((IDocumentPaginatorSource)flowdoc).DocumentPaginator。