WPF:Documents文档--Annomation批注(1)
AnnotatedDocumentViewer批注文档浏览
1、实现功能:
- 文档右键菜单创建和删除批注命令
- ListBox显示批注创建时间(排序)和内容
- 选定一个批注,流文档显示到对应批注锚定
2、关注词:
- 批注XML架构及内容组织:
- AnnotationService+AnnotationStore+IAnchorInfo
- Convert.FromBase64String+XamlReader.Load+TextRange
- 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的数据模板:
- TextBlock内容中[]里面绑定批注数据区AnnotationStore的时间属性CreationTime,
- 其后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格式数据:
- 把Base64格式的string 使用Convert.FromBase64String转换为字节数字byte[]
- MemoryStream初始化字节数组为内存流(使用using自释放内存)
- 使用XamlReader.Load把(Xaml输入的数据)内存流转换为Section根元素。
- 把Section元素的内容构造为TextRange元素。
- 返回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显示
- AnnotationService.Enable(AnnotationStory)
- 绑定批注存储的内容到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());
}
批注绑定方法代码:
- ListBox数据上下文赋值为批注集
- 使用批注的创建时间属性CreationTime作为降序,构造排序描述类SortDescription
- 获取ListBox的集合视图ICollectionSource
- 集合视图的排序集合添加上述的排序描述实例
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);}
批注选择时定位显示批注锚定位置:
- 选择项转换为批注类Annotation,并在AnnotationHelper下获取批注信息
- 获取批注实例的锚定对象TextAnchor
- 获取锚定对象的文本定位位置点TextPointer
- 把锚定点当前位置段落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)相关推荐
- WPF:Documents文档--Annomation批注(3)
AnnotationStyling批注样式 1.实现效果 可以选择不同便笺样式,对所有批注应用样式 选择文本后实现对批注的文本.墨迹便笺创建.删除 对选择文本的部分创建高亮不同颜色的批注,及实现清除命 ...
- 如何利用Word 2016为文档添加批注
在日常工作中,某些文件需要领导审阅或者经过大家讨论后才能够执行,所以就需要在这些文件上进行一些批示.修改.办公软件提供了批注.修订.更改等审阅工具,大大提高了办公效率.在使用Word 2016编辑文档 ...
- Java代码清除Word文档的批注和修订 (Aspose.Words) Java老铁们,亲测有效!
项目里面要求Word文档接受修订,并要去掉批注,常见的工具库有POI和JXL,但有些功能不太强大,用起来也啰嗦,这里用Aspose.Words这个类库来实现一下. 文档链接 在这里 : https:/ ...
- 安卓PDF阅读器使用技巧Ⅱ:PDF文档添加批注、添加下划线及删除技巧
如何更好地使你的PDF文档便于使用?以确保你在后续的阅读/编辑中可以更加得心应手?如果手头只有一部手机的情况下,我们可以借助PDF阅读器的的编辑功能,通过高亮显示.增加下划线等操作,来完成你对文档的重 ...
- word文档添加批注
插入->批注
- WPF中使用流文档灵活地显示内容
WPF中使用流文档灵活地显示内容 by: Markus Egger form: http ...
- mongodb 基本概念:文档(Documents)
mongodb将数据存为BSON 文档格式,BSON 是json文档的二进制格式,但是比json支持更多数据类型,详见:bsonspec.org 1.数据结构 mongodb文档由键值对组成 {fie ...
- 如何批量设置 Word 文档仅允许批注或修订?
概要:在 Word 文档中文档的保护有多种不同的级别.可以设置 Word 文档的打开密码,也可以设置 Word 文档的只读密码,还可以限制 Word 的编辑.并且限制编辑的同时也可以允许批注或者允许批 ...
- 实施文档_Word 2010文档处理案例教程
Word 2010文档处理案例教程 ISBN:978-7-80243-928-3/02 作者:黄桂林 江义火 郭燕 定价:38.00元 出版社:航空工业出版社 适用层次:通用 出版日期:2019-10 ...
最新文章
- 神经网络中激活函数的真正意义?
- 鸟哥的Linux私房菜(基础篇)-第零章、计算机概论(零.3)
- MATLAB R2022 最新中英文版 数据处理
- Flask request接口获取参数
- 数学--数论--Miller_Rabin判断一个大数是不是素数(随机算法)
- C++ vector容器类型
- Python 检测字符串开始值String.StartsWith 方法
- php的工作模式CGI,FastCGI,PHP-CGI与PHP-FPM(转)
- Spring Boot 推荐的基础 POM 文件
- 单例模式中的多线程分析synchronized
- 苹果mac三维动画设计渲染软件:Cinema 4D R20 (c4d r20)
- vim查找和替换字符串
- python KM算法
- [4G5G专题-50]:物理层-数字波束赋型Beamforming及其数学原理
- 服务器开机必须要按f1才能进系统,教你为什么开机必须按F1才能进入系统
- 博客园 首页 新随笔 联系 订阅 管理 如何使用电脑上的谷歌浏览器来调试安卓手机上的移动端页面...
- Elasticsearch 和 MongoDB 对比
- oracle如何总计,按组SQL运行总计(Oracle)
- 微软CEO萨提亚·纳德拉:强化技术密集度,加速转向新经济
- GPL和LGPL协议
热门文章
- mysql 目录位置_更改MySQL数据库目录位置
- “拼多多优惠券”测试的套路,今天让你秒懂~
- 程序人生:软件测试工程师,如何从手工测试转成自动化测试?这可能是每个测试要走的路...
- 【月报】滨哥教我的宝贵经验
- java后端服务运行原理_web服务的后台工作原理
- cmake list all directories
- Disable Auto Detect Keyboard Layout in Win10
- python匿名函数的使用介绍
- php滑动轮播效果,js实现移动端手指滑动轮播图效果
- 基于依存句法分析的资金账户交易画像