Потоковые и фиксированные документы поддерживают такую функциональность как аннотации. Аннотации позволяют добавлять к документам комментарии, выделять какие-то куски текста и т.д.
Для работы с аннотациями определим следующую разметку интерфейса:
<Window x:Class="AnnotationApp.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:AnnotationApp" xmlns:a="clr-namespace:System.Windows.Annotations;assembly=PresentationFramework" mc:Ignorable="d" Title="MainWindow" Height="300" Width="400"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="30" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <ToolBar> <Button Command="a:AnnotationService.CreateTextStickyNoteCommand" FontSize="10"> Комментировать </Button> <Button Command="a:AnnotationService.CreateHighlightCommand" FontSize="10" CommandParameter="{x:Static Brushes.Yellow}"> Выделить </Button> <Button Command="a:AnnotationService.ClearHighlightsCommand" FontSize="10"> Убрать выделение </Button> <Button Command="a:AnnotationService.DeleteStickyNotesCommand" FontSize="10"> Убрать комментарий </Button> </ToolBar> <FlowDocumentScrollViewer x:Name="docViewer" Grid.Row="1"> <FlowDocument FontSize="12"> <Paragraph TextIndent="20"> В 1808 году император Александр ездил в Эрфурт для новой встречи с Наполеоном, и в высшем свете много говорили о важности этого события. В 1809 году близость двух «властелинов мира», как называли Александра и Наполеона, дошла до того, что когда Наполеон объявил войну Австрии, русский корпус выступил за границу, чтобы сражаться на стороне бывшего противника против бывшего союзника, австрийского императора. </Paragraph> </FlowDocument> </FlowDocumentScrollViewer> </Grid> </Window>
Итак, начнем с начала. В строчке xmlns:a="clr-namespace:System.Windows.Annotations;assembly=PresentationFramework"
мы
подключаем пространство имен для аннотаций и отображаем его на префикс a
. Далее в панели инструментов мы создаем ряд кнопок, с
помощью которых мы будем управлять аннотациями. Первая кнопка предназначена для создания текстовой аннотации. Для этого мы используем команду
AnnotationService.CreateTextStickyNoteCommand. Мы также можем использовать одноименный метод у объекта AnnotationService и создать аннотацию
в коде. Затем для следующих кнопок мы добавляем команды создания графической аннотации, выделения цветом и удаления аннотаций. Обратите внимание,
что для выделения цветом мы передаем в команду параметр - в данном случае цвет CommandParameter="{x:Static Brushes.Yellow}"
.
Всего для аннотаций нам доступно шесть команд:
AnnotationService.ClearHighlightsCommand
: удаляет выделение цветом
AnnotationService.CreateHighlightCommand
: добавляет выделение цветом
AnnotationService.CreateInkStickyNoteCommand
: добавляет графический комментарий
AnnotationService.CreateTextStickyNoteCommand
: добавляет обычный текстовый комментарий
AnnotationService.DeleteAnnotationsCommand
: удаляет графические и текстовые комментарии, а также убирает выдеоение цветом
AnnotationService.DeleteStickyNotesCommand
: удаляет графические и текстовые комментарии
При этом нам не надо определять для кнопок обработчики нажатия, так как команды аннотаций все сделают за нас.
Все основные классы по работе с аннотациями хранятся в пространстве имен System.Windows.Annotations. Чтобы сделать аннотации доступными для нашего приложения, их надо подключить. Подключение сделаем в обработчике события загрузки окна. Также удалим поддержку аннотаций из приложения в обработчике закрытия окна:
using System.IO; using System.Windows; using System.Windows.Annotations; using System.Windows.Annotations.Storage; namespace AnnotationApp { public partial class MainWindow : Window { FileStream fs; AnnotationService anService; public MainWindow() { InitializeComponent(); this.Loaded += Window_Loaded; this.Unloaded += Window_Unloaded; } private void Window_Loaded(object sender, RoutedEventArgs e) { //инициализация службы аннотаций anService = new AnnotationService(docViewer); // создание связанного потока fs = new FileStream("storage.xml", FileMode.OpenOrCreate); // привязка потока к хранилищу аннотаций AnnotationStore store = new XmlStreamStore(fs); store.AutoFlush = true; // включение службы anService.Enable(store); } private void Window_Unloaded(object sender, RoutedEventArgs e) { if (anService != null && anService.IsEnabled) { anService.Store.Flush(); anService.Disable(); fs.Close(); } } } }
Итак, в данном коде мы создаем службу аннотаций (класс AnnotationService) и ему в конструктор передаем объект контейнера документа. В данном случае мы передаем переменную docViewer, которая представляет объект FlowDocumentScrollViewer, определенный в xaml. Затем создаем поток, по которому создаем хранилище аннотаций - AnnotationStore. С помощью метода Enable делаем доступным хранилище аннотаций для объекта docViewer. Обратите внимание, что для одного контейнера документа мы можем создать один объект AnnotationService и один объект AnnotationStore. Для нового документа придется создавать эти объекты заново. Файл storage.xml будет хранить у нас аннотации, которые затем будут загружаться в документе. Пока он не создан, поэтому установим режим OpenOrCreate.
Теперь загрузим приложение и выделим часть текста - нам станут доступны кнопки с вышеописанными командами. Попробуем создать аннотацию:
После закрытия приложения наша аннотация будет сохранена в файл и затем при новом открытии программы будет подгружаться в документ.