AnnotatedDocumentViewer批注文档浏览

1、实现功能:

  1. 文档右键菜单创建和删除批注命令
  2. ListBox显示批注创建时间(排序)和内容
  3. 选定一个批注,流文档显示到对应批注锚定

2、关注词:

  1. 批注XML架构及内容组织:
  2. AnnotationService+AnnotationStore+IAnchorInfo
  3. Convert.FromBase64String+XamlReader.Load+TextRange
  4. AnnotationService.Enable(AnnotatinoStore)

3、静态组织:
界面xaml:

<!-- Annotations List -->
<ListBoxName="annotationsListBox"Grid.Row="2"SelectionChanged="annotationsListBox_SelectionChanged"ItemsSource="{Binding}"Template="{StaticResource AnnotationsListTemplate}"ItemTemplate="{StaticResource AnnotationDataTemplate}" />

ListBox模板Template:简单设置竖滚动条+StackPanel容器

<!--To Replace ListBox Template with Template that Allows TextWrapping andalso provides a vertical scrollbar when the wrapped text extends below the bottom of the list box -->
<ControlTemplate x:Key="AnnotationsListTemplate"><ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" ><StackPanel IsItemsHost="True" /></ScrollViewer>
</ControlTemplate>

ListItem的数据模板:

  1. TextBlock内容中[]里面绑定批注数据区AnnotationStore的时间属性CreationTime,
  2. 其后TextBlock.Text绑定到批注数据区AnnotationStore的(AnnotationResource)货物Cargos[1]的内容Content[0]的(string)InnerText
<!-- Data Template for Annotation Item that shows when an annotation wascreated, and what data the annotation contains.  -->
<DataTemplate x:Key="AnnotationDataTemplate"><TextBlock Margin="5" TextWrapping="Wrap"><TextBlock FontWeight="Bold" TextWrapping="Wrap">[<TextBlock Text="{Binding Path=CreationTime}" />]</TextBlock><TextBlockText="{Binding Path=Cargos[1].Contents[0].InnerText,Converter={StaticResource AnnotationDataConverter}}"TextWrapping="NoWrap" /></TextBlock>
</DataTemplate>

绑定转换string》TextRange.Text(Xml包含的Xaml数据转换为文本Text格式数据:

  1. 把Base64格式的string 使用Convert.FromBase64String转换为字节数字byte[]
  2. MemoryStream初始化字节数组为内存流(使用using自释放内存)
  3. 使用XamlReader.Load把(Xaml输入的数据)内存流转换为Section根元素。
  4. 把Section元素的内容构造为TextRange元素。
  5. 返回TextRang包含的文本Text.
public class AnnotationDataConverter : IValueConverter
{public object Convert(object value, Type targetType, object parameter, CultureInfo culture){// Convert 64 bit binary data into an 8 bit byte array and load// it into a memory buffervar data = System.Convert.FromBase64String(value as string);using (var buffer = new MemoryStream(data)){// Convert memory buffer to object and return textvar section = (Section) XamlReader.Load(buffer);var range = new TextRange(section.ContentStart, section.ContentEnd);return range.Text;}}public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => null;
}

主窗口内容需要一些私有字段协助运行:

private IAnchorInfo _info;//提供批注的锚定信息类
private AnnotationService _service;//批注服务类
private AnnotationStore _store;//批注存储区
private Stream _stream;

4、运行流程:
主窗口初始化时设置好批注存储导入及绑定到ListBox显示

  1. AnnotationService.Enable(AnnotationStory)
  2. 绑定批注存储的内容到ListBox
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{// Load annotations store_stream = new FileStream("storage.xml", FileMode.OpenOrCreate);_service = new AnnotationService(flowDocumentReader);_store = new XmlStreamStore(_stream) {AutoFlush = true};_service.Enable(_store);// Detect when annotations are added or deleted_service.Store.StoreContentChanged +=AnnotationStore_StoreContentChanged;// Bind to annotations in storeBindToAnnotations(_store.GetAnnotations());
}

批注内容变动,触发事件,需重新绑定批注内容到ListBox更新显示

private void AnnotationStore_StoreContentChanged(object sender, StoreContentChangedEventArgs e)
{// Bind to refreshed annotations storeBindToAnnotations(_store.GetAnnotations());
}

批注绑定方法代码:

  1. ListBox数据上下文赋值为批注集
  2. 使用批注的创建时间属性CreationTime作为降序,构造排序描述类SortDescription
  3. 获取ListBox的集合视图ICollectionSource
  4. 集合视图的排序集合添加上述的排序描述实例
private void BindToAnnotations(IList<Annotation> annotations)
{// Bind to annotations in storeannotationsListBox.DataContext = annotations;// Sort annotations by creation timevar sortDescription = new SortDescription{PropertyName = "CreationTime",Direction = ListSortDirection.Descending};var view = CollectionViewSource.GetDefaultView(annotationsListBox.DataContext);view.SortDescriptions.Clear();view.SortDescriptions.Add(sortDescription);}

批注选择时定位显示批注锚定位置:

  1. 选择项转换为批注类Annotation,并在AnnotationHelper下获取批注信息
  2. 获取批注实例的锚定对象TextAnchor
  3. 获取锚定对象的文本定位位置点TextPointer
  4. 把锚定点当前位置段落Paragraph.BringIntoView滚动到显示出
private void annotationsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{var comment = (sender as ListBox).SelectedItem as Annotation;if (comment != null){// IAnchorInfo info;// service is an AnnotationService object// comment is an Annotation object_info = AnnotationHelper.GetAnchorInfo(_service, comment);var resolvedAnchor = _info.ResolvedAnchor as TextAnchor;var textPointer = (TextPointer) resolvedAnchor.BoundingStart;textPointer.Paragraph.BringIntoView();}
}

最后主窗口关闭时处理批注服务类的关闭:

private void MainWindow_Closed(object sender, EventArgs e)
{if (_service != null && _service.IsEnabled){_service.Disable();_stream.Close();}
}

WPF:Documents文档--Annomation批注(1)相关推荐

  1. WPF:Documents文档--Annomation批注(3)

    AnnotationStyling批注样式 1.实现效果 可以选择不同便笺样式,对所有批注应用样式 选择文本后实现对批注的文本.墨迹便笺创建.删除 对选择文本的部分创建高亮不同颜色的批注,及实现清除命 ...

  2. 如何利用Word 2016为文档添加批注

    在日常工作中,某些文件需要领导审阅或者经过大家讨论后才能够执行,所以就需要在这些文件上进行一些批示.修改.办公软件提供了批注.修订.更改等审阅工具,大大提高了办公效率.在使用Word 2016编辑文档 ...

  3. Java代码清除Word文档的批注和修订 (Aspose.Words) Java老铁们,亲测有效!

    项目里面要求Word文档接受修订,并要去掉批注,常见的工具库有POI和JXL,但有些功能不太强大,用起来也啰嗦,这里用Aspose.Words这个类库来实现一下. 文档链接 在这里 : https:/ ...

  4. 安卓PDF阅读器使用技巧Ⅱ:PDF文档添加批注、添加下划线及删除技巧

    如何更好地使你的PDF文档便于使用?以确保你在后续的阅读/编辑中可以更加得心应手?如果手头只有一部手机的情况下,我们可以借助PDF阅读器的的编辑功能,通过高亮显示.增加下划线等操作,来完成你对文档的重 ...

  5. word文档添加批注

    插入->批注

  6. WPF中使用流文档灵活地显示内容

    WPF中使用流文档灵活地显示内容                             by: Markus Egger                             form: http ...

  7. mongodb 基本概念:文档(Documents)

    mongodb将数据存为BSON 文档格式,BSON 是json文档的二进制格式,但是比json支持更多数据类型,详见:bsonspec.org 1.数据结构 mongodb文档由键值对组成 {fie ...

  8. 如何批量设置 Word 文档仅允许批注或修订?

    概要:在 Word 文档中文档的保护有多种不同的级别.可以设置 Word 文档的打开密码,也可以设置 Word 文档的只读密码,还可以限制 Word 的编辑.并且限制编辑的同时也可以允许批注或者允许批 ...

  9. 实施文档_Word 2010文档处理案例教程

    Word 2010文档处理案例教程 ISBN:978-7-80243-928-3/02 作者:黄桂林 江义火 郭燕 定价:38.00元 出版社:航空工业出版社 适用层次:通用 出版日期:2019-10 ...

最新文章

  1. 神经网络中激活函数的真正意义?
  2. 鸟哥的Linux私房菜(基础篇)-第零章、计算机概论(零.3)
  3. MATLAB R2022 最新中英文版 数据处理
  4. Flask request接口获取参数
  5. 数学--数论--Miller_Rabin判断一个大数是不是素数(随机算法)
  6. C++ vector容器类型
  7. Python 检测字符串开始值String.StartsWith 方法
  8. php的工作模式CGI,FastCGI,PHP-CGI与PHP-FPM(转)
  9. Spring Boot 推荐的基础 POM 文件
  10. 单例模式中的多线程分析synchronized
  11. 苹果mac三维动画设计渲染软件:Cinema 4D R20 (c4d r20)
  12. vim查找和替换字符串
  13. python KM算法
  14. [4G5G专题-50]:物理层-数字波束赋型Beamforming及其数学原理
  15. 服务器开机必须要按f1才能进系统,教你为什么开机必须按F1才能进入系统
  16. 博客园 首页 新随笔 联系 订阅 管理 如何使用电脑上的谷歌浏览器来调试安卓手机上的移动端页面...
  17. Elasticsearch 和 MongoDB 对比
  18. oracle如何总计,按组SQL运行总计(Oracle)
  19. 微软CEO萨提亚·纳德拉:强化技术密集度,加速转向新经济
  20. GPL和LGPL协议

热门文章

  1. mysql 目录位置_更改MySQL数据库目录位置
  2. “拼多多优惠券”测试的套路,今天让你秒懂~
  3. 程序人生:软件测试工程师,如何从手工测试转成自动化测试?这可能是每个测试要走的路...
  4. 【月报】滨哥教我的宝贵经验
  5. java后端服务运行原理_web服务的后台工作原理
  6. cmake list all directories
  7. Disable Auto Detect Keyboard Layout in Win10
  8. python匿名函数的使用介绍
  9. php滑动轮播效果,js实现移动端手指滑动轮播图效果
  10. 基于依存句法分析的资金账户交易画像