一、实现功能:数组
二、关注词:架构
三、静态组织:
界面xaml:app
<!-- Annotations List --> <ListBox Name="annotationsListBox" Grid.Row="2" SelectionChanged="annotationsListBox_SelectionChanged" ItemsSource="{Binding}" Template="{StaticResource AnnotationsListTemplate}" ItemTemplate="{StaticResource AnnotationDataTemplate}" />
ListBox模板Template:简单设置竖滚动条+StackPanel容器ide
<!--To Replace ListBox Template with Template that Allows TextWrapping and also 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的数据模板:spa
<!-- Data Template for Annotation Item that shows when an annotation was created, 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> <TextBlock Text="{Binding Path=Cargos[1].Contents[0].InnerText,Converter={StaticResource AnnotationDataConverter}}" TextWrapping="NoWrap" /> </TextBlock> </DataTemplate>
绑定转换string》TextRange.Text(Xml包含的Xaml数据转换为文本Text格式数据:code
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 buffer var data = System.Convert.FromBase64String(value as string); using (var buffer = new MemoryStream(data)) { // Convert memory buffer to object and return text var 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; }
主窗口内容须要一些私有字段协助运行:xml
private IAnchorInfo _info;//提供批注的锚定信息类 private AnnotationService _service;//批注服务类 private AnnotationStore _store;//批注存储区 private Stream _stream;
四、运行流程:
主窗口初始化时设置好批注存储导入及绑定到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 store BindToAnnotations(_store.GetAnnotations()); }
批注内容变更,触发事件,需从新绑定批注内容到ListBox更新显示排序
private void AnnotationStore_StoreContentChanged(object sender, StoreContentChangedEventArgs e) { // Bind to refreshed annotations store BindToAnnotations(_store.GetAnnotations()); }
批注绑定方法代码:事件
private void BindToAnnotations(IList<Annotation> annotations) { // Bind to annotations in store annotationsListBox.DataContext = annotations; // Sort annotations by creation time var sortDescription = new SortDescription { PropertyName = "CreationTime", Direction = ListSortDirection.Descending }; var view = CollectionViewSource.GetDefaultView(annotationsListBox.DataContext); view.SortDescriptions.Clear(); view.SortDescriptions.Add(sortDescription); }
批注选择时定位显示批注锚定位置:
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(); } }