48
Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock nie nadają się do wyświetlania dużej ilości formatowanego tekstu (np. dokumentów czy pomocy): 1/48

wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Embed Size (px)

Citation preview

Page 1: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Programowanie w technologii .NETwykład 9 – Dokumenty

Kontrolki Label i TextBlock nie nadają się do wyświetlania dużej ilości formatowanego tekstu (np. dokumentów czy pomocy):

1/48

Page 2: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

• Dokumenty pozwalają prezentować dużą ilość tekstu w czytelny, wygodny sposób: obsługa kolumn, podziału na strony, dzielenia słów, ...

Dokumenty w WPF dzielą się na dwie kategorie:• Fixed documents – dokumenty przeznaczone do wydruku, o ustalonej pozycji

całej zawartości, stronicowaniu; są odpowiednikiem plików PDF. Ważne, gdy chcemy wydrukować coś bez zmian.

• Flow documents – przeznaczone do oglądania w okienku, ich zawartość układana jest automatycznie – dostosowując się do okna i sposobu wyświetlania; odpowiadają dokumentom HTML.

Dokument musi być wyświetlany w kontenerze:• Fixed documents – w kontenerze DocumentViewer• Flow documents – do dyspozycji mamy kontenery FlowDocumentReader,

FlowDocumentPageViewer i FlowDocumentScrollViewer

Wszystkie te kontenery są tylko do odczytu. Poza tym, mamy do dyspozycji API do tworzenia fixed documents oraz kontrolkę RichTextBox do edycji flow documents.

2/48

Page 3: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Flow Documents

• W tym typie dokumentów zawartość dostosowuje się do kontenera. Przeznaczone do wyświetlania na ekranie.

• Jest pozbawiony wielu wad HTMLa. Domyślnie zawartość HTML wypełnia okno – co może utrudniać czytanie, jeśli szerokość okienka (i długość linii) jest duża. Rozwiązaniem jest odgórne ograniczenie szerokości, ale wiąże się to ze stratą miejsca (marginesy).

• Flow Document dodaje m. in. paginację (podział na strony), formaty wielokolumnowe, dzielenie słów i możliwość zmiany ustawień użytkownika.

Do tworzenia dokumentu typu flow służy klasa FlowDocument.Nowy dokument możemy tworzyć jako osobny plik lub też umieścić go w

istniejącym oknie, wykorzystując jeden z dostępnych kontenerów (w przykładzie użyjmy FlowDocumentScrollViewer).

<Window ...> <FlowDocumentScrollViewer> <FlowDocument> ... </FlowDocument> </FlowDocumentScrollViewer></Window>

3/48

Page 4: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Flow Elements

• Nie możemy umieścić tekstu bezpośrednio w dokumencie. Flow document tworzony jest z flow elements.

• Nie dziedziczą one z klas UIElement i FrameworkElement, lecz tworzą własną, odrębną hierarchię klas ContentElement i FrameworkContentElement.

• Są prostsze, niż elementy poznawane dotąd, ale obsługują podobny zestaw zdarzeń i własności.

• Podstawowa różnica: nie odpowiadają za renderowanie samych siebie. Zajmuje się tym kontener, który je przechowuje (co pozwala na optymalizację).

• Domyślnie nie przyjmują też focusa (Focusable ustawione na false).

Dwa podstawowe typy Flow Elements:

• Block elements (elementy blokowe) – służą do grupowania innych elementów. Np. paragraf (Paragraph) może zawierać kilka sekcji różnie sformatowanego tekstu.

• Inline elements (elementy liniowe) – są zagnieżdżane w elementach blokowych (lub innych elementach liniowych). Np. element Run zawiera pewien tekst, który możemy umieścić w paragrafie.

Ten model zawartości pozwala na wielokrotne poziomy zagnieżdżenia (np. element Bold w elemencie Underline – model bardzo podobny do HTMLa)

4/48

Page 5: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Elementem najwyższego poziomu musi być element blokowy (np. Paragraph):

<Window ...> <FlowDocumentScrollViewer>

<FlowDocument><Paragraph>Hello, world!</Paragraph>

</FlowDocument> </FlowDocumentScrollViewer></Window>

5/48

Page 6: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Nie ma ograniczenia, ilu elementów najwyższego poziomu użyjemy:

<Window ...> <FlowDocumentScrollViewer> <FlowDocument> <Paragraph>Hello, world!</Paragraph> <Paragraph>A to jest drugi paragraf.</Paragraph> </FlowDocument> </FlowDocumentScrollViewer></Window>

Pasek przewijania jest dodawany automatycznie, a czcionka jest pobrana z ustawień systemowych, a nie okna zawierającego kontener.

Domyślnie FlowDocumentScrollViewer.IsSelectionEnabled jest ustawione na true.

6/48

Page 7: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Formatowanie elementów

• Foreground, Background – pędzle wypełniające pierwszy plan i tło elementu• FontFamily, FontSize, FontStretch, FontStyle, FontWeight – własności

dotyczące kroju pisma• ToolTip – podpowiedź wyświetlana po zatrzymaniu się na elemencie• Style – styl definiujący wygląd elementu• BorderBrush, BorderThickness – obramowanie elementu• Margin – odległość między elementem a kontenerem lub elementem sąsiednim.

Domyślnie odległość między Block elements (np. dwoma paragrafami) to 18 jednostek (jeśli chcemy to zmniejszyć, należy zmniejszać z obu stron).

• Padding – odstęp między krawędzią elementu a elementem zagnieżdżonym• TextAlignment – wyrównanie w poziomie (Left, Right, Center lub Justify)• LineHeight – odległość między liniami zagnieżdżonego tekstu.• LineStackingStrategy – określa, w jaki sposób linie są oddzielone, gdy zawierają

tekstu o różnych wielkościach czcionki (MaxHeight wybiera najwyższy rozmiar czcionki, BlockLineHeight używa wartości LineHeight dla wszystkich linii)

Ponadto:• TextDecorations (udostępniane przez Paragraph i wszystkie elementy inline) –

Strikethrough, Overline, Underline lub dowolna ich kombinacja.• Typography – szczegóły dotyczące sposobu renderowania tekstu.

7/48

Page 8: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Elementy blokowe

Paragraph i Run

Paragraf nie zawiera tekstu, ale kolekcję elementów liniowych – Paragraph.Inlines (może on zatem zawierać nie tylko tekst).Aby umieścić tekst w paragrafie, musi znaleźć się on w elemencie Run:

<Paragraph> <Run>A to jest drugi paragraf.</Run></Paragraph>

Jeśli go nie podamy, zostanie utworzony automatycznie, ale należy o tym pamiętać, jeśli chcemy sięgnąć do tego tekstu programistycznie:

<Paragraph Name="paragraf">Hello, world!</Paragraph>

((Run)paragraf.Inlines.FirstInline).Text = "Dzień dobry!";

Lepszym pomysłem może być umieszczanie tekstu, który chcemy modyfikować w elemencie Span (aby móc go nazwać i sięgać do niego bezpośrednio).

8/48

Page 9: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Klasa Paragraph zawiera własność TextIndent, która pozwala ustawić rozmiar wcięcia pierwszego wiersza.

W odróżnieniu od HTML, w WPF nie ma elementów nagłówków (należy używać odpowiednio sformatowanych paragrafów).

List

Reprezentuje punktowaną lub numerowana listę – wybrać to można przy pomocy własności MarkerStyle:

• Disc• Box• Circle• Square• Decimal (domyślnie zaczyna się od 1, ale można wybrać inny StartingIndex)• LowerLatin (a, b, c).• UpperLatin (A, B, C).• LowerRoman (i, ii, iii, iv).• UpperRoman (I, II, III, IV).• None – bez znacznika

MarkerOffset pozwala ustawić odstęp między znacznikiem a elementem listy.

9/48

Page 10: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Wewnątrz listy zagnieżdżamy elementy ListItem, reprezentujące poszczególne podpunkty.Każdy ListItem musi zawierać element blokowy (np. Paragraph).

<FlowDocument> <Paragraph>Tematy projektów</Paragraph> <List> <ListItem> <Paragraph>Sklep</Paragraph> </ListItem> <ListItem> <Paragraph>Miejski Dom Kultury</Paragraph> </ListItem> <ListItem> <Paragraph>Lista zadań</Paragraph> </ListItem> <ListItem> <Paragraph>Wizard klas</Paragraph> </ListItem> </List></FlowDocument>

10/48

Page 11: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Table

Przeznaczona do wyświetlania zawartości w postaci tabeli. Jest wzorowana na <table> z HTMLa.

Aby stworzyć tabelę, należy:1. Umieścić element TableRowGroup w elemencie Table. TableRowGroup zawiera

grupę wierszy. Pozwala nadać jedno formatowanie kilku wierszom jednocześnie.2. Umieścić element TableRow w elemencie TableRowGroup. TableRow

reprezentuje pojedynczy wiersz.3. W TableRow umieścić element TableCell dla każdej kolumny wiersza.4. W TableCell umieścić element blokowy (przeważnie Paragraph), do

przechowywania zawartości komórki.

11/48

Page 12: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

<FlowDocument> <Paragraph FontSize="16pt">Oddanych zadań:</Paragraph> <Table> <TableRowGroup Paragraph.TextAlignment="Center"> <TableRow FontWeight="Bold"> <TableCell> <Paragraph>Nr</Paragraph> </TableCell> <TableCell> <Paragraph>Temat</Paragraph> </TableCell> <TableCell> <Paragraph>Oddanych</Paragraph> </TableCell> </TableRow> ... </TableRowGroup> </Table></FlowDocument>

12/48

Page 13: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

• W przeciwieństwie do kontenera Grid, komórki w Table są wypełniane w kolejności (wg pozycji).

• Domyślnie kolumny rozmieszczane są równomiernie. Można samodzielnie określić rozmiar lub proporcje (ale nie oba naraz, nie możemy łączyć kolumn o ustalonym rozmiarze z proporcjonalnymi):

<Table.Columns> <TableColumn Width="*"/> <TableColumn Width="3*"/> <TableColumn Width="*"/></Table.Columns>

• Można również określić ColumnSpan lub/i RowSpan.• CellSpacing określa odstęp między komórkami.• Każda komórka może być formatowana osobno.• Nie ma zbyt dobrego wsparcia dla obramowań: istnieją BorderThickness,

BorderBrush (własności TableCell), ale rysują osobną krawędź wokół każdej komórki; BorderThickness i BorderBrush w klasie Table to krawędź wokół całej tabeli.

13/48

Page 14: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Section

Sekcja jest analogiczna do elementu <div> z HTMLa.Służy do grupowania elementów blokowych, by móc nadać im jeden styl formatowania.

<Section FontFamily="Comic Sans MS"Background="LightSteelBlue">

<Paragraph > ... </Paragraph> <Paragraph > ... </Paragraph></Section>

(Oczywiście można też używać w połączeniu ze stylami.)

(działa to dla czcionek, bo są dziedziczone, a dla tła, bo domyślnie w paragrafie jest przezroczyste i widać tło sekcji)

14/48

Page 15: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

BlockUIContainer• Pozwala na umieszczenie w dokumencie (w miejscu elementu blokowego)

elementów dziedziczących z UIElement.• Pozwala na dodawanie np. przycisków, pól wyboru, a nawet całych paneli czy

gridów ze złożoną zawartością. Jedyne ograniczenie: pojedyncze dziecko.• Jest to przydatne, gdy chcemy połączyć dokument z kontrolkami zapewniającymi

pewną interakcję z użytkownikiem, np. przyciski w systemie pomocy lub pola tekstowe w formularzu.

<Paragraph> Naciśnij, aby uzyskać więcej pomocy.</Paragraph><BlockUIContainer> <Button HorizontalAlignment="Left" Padding="5"> Pomoc </Button></BlockUIContainer>

15/48

Page 16: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Elementy liniowe

• Run – zawiera zwykły tekst, można ustawić mu formatowanie, choć częściej stosuje się do tego Span; tworzony domyślnie np. w paragrafach

• Span – (analogiczne do HTMLowego <span>) opakowuje dowolną liczbę elementów inline, zazwyczaj używany do formatowania fragmentu tekstu (w tym celu opakowujemy w niego tekstu lub np. element Run); przydatne do nazwania fragmentu dokumentu (aby móc odwołać się do niego w kodzie)

• Bold, Italic, and Underline – umożliwiają nałożenie odpowiedniego formatowania na tekst (zazwyczaj lepiej jest jednak opakować tekst w Span i ustawić odpowiedni styl)

• Hyperlink – reprezentuje odnośnik (podnosi zdarzenie Click)• LineBreak – dodaje złamanie linii• InlineUIContainer – pozwala na umieszczanie elementów dziedziczących po

UIElement w miejscu elementów inline.• Floater, Figure – umożliwia wstawienie specjalnie traktowanego obszaru do

wyświetlania obrazów, wyróżnionych informacji i innej zawartości

16/48

Page 17: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Białe znakiNa początku lub końcu elementu są ignorowane, ale przed elementem inline – nie. Dlatego to działa źle:

<Paragraph>Do końca grudnia<Bold> należy </Bold>przygotować prototyp interfejsu.</Paragraph>

a to dobrze:

<Paragraph>Do końca grudnia <Bold>należy</Bold> przygotować prototyp interfejsu.</Paragraph>

Można też używać:

<Run xml:space="preserve"> a b c </Run>

17/48

Page 18: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Floater

Element, który pozwala umieścić pewną zawartość obok głównego dokumentu:

<Paragraph> Przykładowy tekst. <Floater Style="{StaticResource Cytat}"> <Paragraph>...cytat...</Paragraph> </Floater> Dalszy ciąg przykładowego tekstu..</Paragraph><Paragraph> Kolejny akapit.</Paragraph>

18/48

Page 19: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Styl użyty w przykładzie:

<Style x:Key="Cytat"> <Setter Property="Paragraph.FontSize" Value="24"/> <Setter Property="Paragraph.FontStyle" Value="Italic"/> <Setter Property="Paragraph.Foreground" Value="SteelBlue"/> <Setter Property="Paragraph.Padding" Value="5"/> <Setter Property="Paragraph.Margin" Value="15,10,5,10"/></Style>

Możemy ograniczyć zajmowane przez niego miejsce i ręcznie określić położenie:

<Floater Style="{StaticResource Cytat}" Width="200" HorizontalAlignment="Left"> <Paragraph>...</Paragraph></Floater>

Aby dostosować wygląd, możemy też ustawić własności Background, BorderBrush, BorderThickness, Margin i Padding (pozostałe elementy inline tego nie mają, tylko Floater i Figure).

19/48

Page 20: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Możemy go użyć do wyświetlenia obrazka (element Image wewnątrz BlockUIContainer lub InlineUIContainer). Niestety, Floater nie dostosowuje szerokości do zawartości.

<Paragraph>...</Paragraph><Paragraph>...<Floater Width="100" Padding="5,0,5,0" HorizontalAlignment="Right"> <BlockUIContainer> <Image Source="Masqueofthereddeath.jpg"></Image> </BlockUIContainer></Floater>...</Paragraph>

20/48

Page 21: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Figure

Podobna do Floatera, ale daje więcej kontroli nad położeniem.uwaga: wiele poniższych własności (np. HorizontalAnchor, VerticalOffset, HorizontalOffset) nie jest wspieranych przez kontener FlowDocumentScrollViewer, dlatego w przykładzie użyjemy FlowDocumentReader.

• Width – szerokość; poza stała wartością, jak w Floaterze, możemy podać wartość proporcjonalną (np. „0.25 content”, „2 Column”).

• Height – wysokość – Floater dostosowywał ją do zawartości, tu możemy określić ją ręcznie

• HorizontalAnchor – zamiast HorizontalAlignment z klasy Floatera; pozwala orientować również względem strony lub kolumny (poza np. ContentCenter mamy PageCenter i ColumnCenter).

• VerticalAnchor – pozwala wyrównać do bieżącej linii, kolumny, strony• HorizontalOffset, VerticalOffset – pozwalają na przesunięcie figury względem

miejsca zakotwiczenia• WrapDirection – określa, czy tekst może opływać figurę z jednej czy obu stron

21/48

Page 22: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

<FlowDocumentReader><FlowDocument> <Paragraph>...</Paragraph> <Paragraph>... <Figure Width="0.5 column" Padding="5,0,5,0" HorizontalAnchor="ColumnLeft"> <BlockUIContainer> <Image Source="Masqueofthereddeath.jpg" /> </BlockUIContainer> </Figure> ...</Paragraph></FlowDocument></FlowDocumentReader>

22/48

Page 23: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Interakcja z elementami(uwaga: tekst musimy ręcznie umieszczać w elementach Run)

// Pierwszy fragment zdaniaRun runFirst = new Run();runFirst.Text = "Oto ";// Wytłuszczony tekstBold bold = new Bold();Run runBold = new Run();runBold.Text = "dynamicznie wygenerowany";bold.Inlines.Add(runBold);// Koniec zdaniaRun runLast = new Run();runLast.Text = " dokument.";// Dodawanie fragmentów do paragrafuParagraph paragraph = new Paragraph();paragraph.Inlines.Add(runFirst);paragraph.Inlines.Add(bold);paragraph.Inlines.Add(runLast);// Utworzenie dokumentu i dodanie paragrafuFlowDocument document = new FlowDocument();document.Blocks.Add(paragraph);// Wyświetlenie dokumentudocViewer.Document = document;

23/48

Page 24: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

A czego użyć, aby przeglądać (i modyfikować) gotowy dokument?• kolekcja FlowDocument.Blocks zwraca elementy blokowe;

FlowDocument.Blocks.FirstBlock zwraca pierwszy, a FlowDocument.Blocks.LastBlock – ostatni element kolekcji

• w celu przeglądania elementów blokowych: Block.NextBlock (lub Block.PreviousBlock). Ponadto kolekcja Block.SiblingBlocks pozwala przeglądać elementy tego samego poziomu co aktualny

• wiele elementów blokowych zawiera inne elementy (np. List zawiera elementy ListItem, Section zawiera kolekcję Blocks, Paragraph zawiera Inlines.

Jeśli celem jest wymienienie fragmentu tekstu w dokumencie, najlepiej jest wydzielić ten fragment w postaci elementu Span. Możemy rozpoznawać je po nazwie, albo np. po Tagu (jeśli szukamy elementu, który występuje więcej niż raz).

24/48

Page 25: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Justowanie

• Domyślnie dokumenty są wyjustowane (TextAlignment – Justify).• Ustawienie FlowDocument.IsOptimalParagraphEnabled na true włącza opcję

optymalnego dzielenia wierszy (podziały linii są ustawiane tak, by jak najlepiej rozłożyć odstępy w dokumencie)

Ustawiając FlowDocument.IsHyphenationEnabled na true włączamy dzielenie słów (do ustalenia podziału wykorzystywany jest słownik).

25/48

Page 26: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Kontenery Flow DocumentSą tylko do odczytu. Wszystkie obsługują drukowanie i zoom.

• FlowDocumentScrollViewer – cały dokument z paskiem przewijania. Nie obsługuje paginacji, ani wielu kolumn.

• FlowDocumentPageViewer – dzieli dokument na wiele stron.• FlowDocumentReader – łączy cechy obu powyższych: użytkownik wybiera który

rodzaj widoku go interesuje.

Zmiana kontenera jest prosta:

<FlowDocumentPageViewer> <FlowDocument> <Paragraph>Jeden akapit tekstu.</Paragraph> </FlowDocument></FlowDocumentPageViewer>

Jak prosty kontener może też służyć TextBlock – może przechowywać elementy liniowe (inline), oferuje zawijanie (TextWrapping) i ucinanie (TextTrimming) tekstu. To ostatnie może przyjmować wartość: None, WordEllipse (niemieszczące się słowa zastępuje „...”), CharacterEllipse (niemieszczące się znaki zastępuje „...”).

26/48

Page 27: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Zoom

• Ustawiany przy pomocy własności Zoom kontenera. Jest to wartość w procentach.• Można ustawiać ją ręcznie, używać metod IncreaseZoom() i DecreaseZoom()

(zwiększają lub zmniejszają o ZoomIncrement) lub pozwolić wybrać użytkownikowi (FlowDocumentScrollViewer daje do dyspozycji suwak powiększenia):

<FlowDocumentScrollViewer MinZoom="50" MaxZoom="1000" Zoom="100" ZoomIncrement="5" IsToolBarVisible="True"> ...</FlowDocumentScrollViewer>

Elementy Floater lub Figure o ustalonym rozmiarze też są powiększane proporcjonalnie.

27/48

Page 28: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Strony i kolumny

• Kontener FlowDocumentPageViewer może dzielić długi dokument na strony – zastępuje to scrollowanie.

• A jeśli okno będzie dość szerokie, tekst zostanie podzielony na kolumny.

Uwaga: Floater domyślnie przyjmuje szerokość całej kolumny, Można go zmniejszyć, ale nie powiększyć. Z kolei Figure może zajmować kilka kolumn.

• FlowDocumentReader również obsługuje podział na strony: można wybrać widok jednej strony (jak we FlowDocumentPageViewer) lub dwóch stron obok siebie.

28/48

Page 29: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Podział na strony i kolumny możemy kontrolować w klasie FlowDocument lub Paragraph.

FlowDocument:• ColumnWidth – preferowany rozmiar kolumny (działa jako rozmiar minimalny)• IsColumnWidthFlexible – decyduje, czy kontener może dopasować rozmiar

kolumny (jeśli false, użyta jest dokładna wartość ColumnWidth, jeśli true – ColumnWidth to rozmiar minimalny). Domyślnie: true;

• ColumnGap – odstęp między kolumnami• ColumnRuleWidth i ColumnRuleBrush – szerokość i wypełnienie pionowej

kreski między kolumnami

Paragraph:• KeepTogether – czy paragraf może być podzielony na strony (gdy true: cały

paragraf znajdzie się na jednej stronie)• KeepWithNext – czy można oddzielić końcem strony ten paragraf od następnego

(przeważnie: do nagłówków)• MinOrphanLines – jak paragraf jest dzielony na strony; minimalna liczba linii,

jaka ma pozostać na poprzedniej stronie (gdy się nie mieszczą – przenoszony jest cały paragraf)

• MinWidowLines – minimalna liczba linii, jaka ma być przeniesiona na następną stronę

29/48

Page 30: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Odczyt dokumentu z pliku

• Do ładowania zawartości do kontenera służy klasa XamlReader (z System.Windows.Markup). W poniższym kodzie pominięto obsługę błędów:

using (FileStream fs = File.Open(documentFile, FileMode.Open)){ FlowDocument document = XamlReader.Load(fs) as FlowDocument; if (document == null) { MessageBox.Show("Nie udało się odczytać dokumentu."); } else { flowContainer.Document = document; }}

• Podobnie łatwo zapisać dokument z kontenera:

using (FileStream fs = File.Open(documentFile, FileMode.Create)){ XamlWriter.Save(flowContainer.Document, fs);}

30/48

Page 31: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Drukowanie

• Wystarczy wywołać metodę Print() z kontenera. Wyświetla on okno drukowania z wyborem drukarki i ustawień.

• Drukowanie działa przez system poleceń, zatem wystarczy dodać przycisk (lub skorzystać z Ctrl+P):

<Button Command="ApplicationCommands.Print" CommandTarget="docViewer">Print</Button>

W podobny sposób obsługiwane jest np. wyszukiwanie i powiększenie.

31/48

Page 32: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Edycja Flow Document

Kontrolka RichTextBox umożliwia edycję flow documents.

Ładowanie pliku – można zadeklarować dokument od razu wewnątrz RichTextBox:

<RichTextBox> <FlowDocument> <Paragraph>Dokument do edycji.</Paragraph> </FlowDocument></RichTextBox>

Można też wczytać go przy pomocy XamlReader.Load(). Jeśli chcemy czytać inne formaty, pomocna jest klasa System.Windows.Documents.TextRange.

Dozwolone typy:• DataFormat.Xaml – zawartość XAML• DataFormats.Rtf – rich text (*.rtf)• DataFormats.XamlPackage – zawartość XAML z osadzonymi obrazami• DataFormats.Text – zwykły tekst

32/48

Page 33: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

OpenFileDialog openFile = new OpenFileDialog();openFile.Filter = "RichText Files (*.rtf)|*.rtf|All Files (*.*)|*.*";if (openFile.ShowDialog() == true){ TextRange documentTextRange = new TextRange( richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd); using (FileStream fs = File.Open(openFile.FileName, FileMode.Open)) { // po rozszerzeniu rozpoznajemy typ pliku: if (Path.GetExtension(openFile.FileName).ToLower() == ".rtf") { documentTextRange.Load(fs, DataFormats.Rtf); } else { documentTextRange.Load(fs, DataFormats.Xaml); } }}

(najpierw tworzymy TextRange obejmujący zawartość dokumentu, którą chcemy wymienić)

33/48

Page 34: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Zapis pliku:

SaveFileDialog saveFile = new SaveFileDialog();saveFile.Filter ="XAML Files (*.xaml)|*.xaml|RichText Files (*.rtf)|*.rtf|All Files (*.*)|*.*";if (saveFile.ShowDialog() == true){ // cały zakres dokumentu: TextRange documentTextRange = new TextRange( richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd); // Jeśli plik istnieje, zostanie nadpisany using (FileStream fs = File.Create(saveFile.FileName)) { if (Path.GetExtension(saveFile.FileName).ToLower() == ".rtf") { documentTextRange.Save(fs, DataFormats.Rtf); } else { documentTextRange.Save(fs, DataFormats.Xaml); } }}

34/48

Page 35: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Elementem najwyższego poziomu będzie Section (tylko takie pliki XAML są akceptowane).

Formatowanie tekstu: Kontrolka RichTextBox obsługuje polecenia związane z edycją i formatowaniem dokumentów, dlatego aby obsługiwać np. zmiany formatu, wystarczy dodać przyciski na pasku narzędzi.

35/48

Page 36: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Fixed Documents

• Fixed documents są mnie elastyczne niż Flow documents.• Służą jako dokument gotowy do wydruku, który można przenosić i drukować w

niezmienny formacie (na wzór PDF).• Wykorzystują pliki XPS (XML Paper Specification).• Sterowniki drukarki w Viście i Windows 7 pozwalają na drukowanie dowolnych

dokumentów do formatu XPS.• Format XPF to archiwum zip zawierające dokument w postaci XML, wraz z

obrazkami, osadzonymi czcionkami, etc.

Dokument XPS możemy wyświetlić w kontenerze DocumentViewer.

XpsDocument doc = new XpsDocument("filename.xps", FileAccess.Read);docViewer.Document = doc.GetFixedDocumentSequence();doc.Close();

W dokumentach XPS układ i rozmiar strony są ustalone, dokument przeznaczony jest od razu do wydruku.

36/48

Page 37: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Annotations

Adnotacje. Pozwalają dodać komentarz lub wyróżnić fragment tekstu w dokumencie flow lub fixed.

Dwa rodzaje:• Highlighting – wybranie części tekstu i wyróżnienie go kolorem (zakreślacz).• Sticky notes – dołączenie do fragmentu tekstu pływającej ramki z informacją.

37/48

Page 38: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

• Wszystkie cztery rodzaje kontenerów obsługują adnotacje.• Przedtem jednak musimy wykonać dwa kroki: włączyć możliwość stosowania

adnotacji i dodać kontrolki, przy pomocy których użytkownik będzie je dodawał.

Klasy adnotacji• AnnotationService – klasa zajmująca się usługą adnotacji (aby je udostępnić,

należy stworzyć jej obiekt)• AnnotationStore – zajmuje się składowanie dodanych adnotacji. Udostępnia

metody pozwalające na dodawanie i usuwanie pojedynczych adnotacji oraz zdarzenia podnoszone w momencie ich dodawania i zmiany. Jest to klasa abstrakcyjna, dziedziczy z niej klasa XmlStreamStore, która składuje adnotacje w formacie XML.

• AnnotationHelper – udostępnia kilka statycznych metod do posługiwania się adnotacjami.

38/48

Page 39: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Włączanie obsługi

// A stream for storing annotation.private MemoryStream annotationStream;// The service that manages annotations.private AnnotationService service;

protected void window_Loaded(object sender, RoutedEventArgs e){ // Create the AnnotationService for your document container. service = new AnnotationService(docReader); // Create the annotation storage. annotationStream = new MemoryStream(); AnnotationStore store = new XmlStreamStore(annotationStream); // Enable annotations. service.Enable(store);}

• Zamiast MemoryStream (który zniknie po zakończeniu aplikacji) możemy użyć FileStream, co spowoduje zapisanie utworzonych adnotacji do pliku.

• Jeśli już były jakieś adnotacje w strumieniu, gdy wywołano AnnotationService.Enable(), wówczas od razu się one pojawią.

39/48

Page 40: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

protected void window_Unloaded(object sender, RoutedEventArgs e){ if (service != null && service.IsEnabled) { // Flush annotations to stream. service.Store.Flush(); // Disable annotations. service.Disable(); annotationStream.Close(); }}

Uwaga: Każdy kontener dokumentu może mieć jedną instancję AnnotationService. Każdy dokument powinien mieć własną instancję AnnotationStore (przy otwieraniu nowego dokumentu, należy wyłączyć usługę, zamknąć strumień, stworzyć nowy Store i ponownie uruchomić usługę).

40/48

Page 41: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Dodawanie adnotacji

(dwa sposoby)

Metody klasy AnnotationHelper:• CreateTextStickyNoteForSelection()• CreateInkStickyNoteForSelection()• DeleteTextStickyNotesForSelection()• DeleteInkStickyNotesForSelection()• CreateHighlightsForSelection()• ClearHighlightsForSelection()

Wszystkie działają dla aktualnego zaznaczenia.

Lub odpowiadające im polecenia klasy z AnnotationService.

41/48

Page 42: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

<Window ... xmlns:annot= "clr-namespace:System.Windows.Annotations;assembly=PresentationFramework" ...>...

<ToolBar DockPanel.Dock="Top"> <Button Command="annot:AnnotationService.CreateTextStickyNoteCommand">Text Note</Button></ToolBar>

• (Naciśnięcie przycisku spowoduje dodanie okienka, w którym użytkownik może pisać tekst adnotacji.)

• (uwaga: gdy Button jest na toolbarze, możemy pominąć CommandTarget, gdyż polecenie samo znajdzie swój cel.)

42/48

Page 43: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Możemy dostarczyć dodatkowych informacji dodawanej adnotacji: np. nazwę użytkownika, który ją dodał.

<Button Command="annot:AnnotationService.CreateTextStickyNoteCommand"CommandParameter="{StaticResource AuthorName}"> Text Note</Button>

Z nazwą pobraną z zasobów:

<Window.Resources> <sys:String x:Key="AuthorName">[Anonymous]</sys:String></Window.Resources>

Lub wczytaną z ustawień systemowych:(System.Security.Principal.WindowsIdentity)

WindowsIdentity identity = WindowsIdentity.GetCurrent();this.Resources["AuthorName"] = identity.Name;

43/48

Page 44: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Pozostałe:

<Button Command="annot:AnnotationService.CreateInkStickyNoteCommand"CommandParameter="{StaticResource AuthorName}"> Ink Note</Button><Button Command="annot:AnnotationService.DeleteStickyNotesCommand"> Delete Note(s)</Button>

Dodawanie wyróżnienia wymaga podania koloru. Jest on nakładany na tekst, a zatem powinien być półprzeźroczysty (dwie pierwsze cyfry koloru, to alpha).

<Button Background="Yellow" Width="15" Height="15" Margin="2,0"Command="annot:AnnotationService.CreateHighlightCommand"> <Button.CommandParameter> <SolidColorBrush Color="#54FFFF00"></SolidColorBrush> </Button.CommandParameter></Button>

44/48

Page 45: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

<Button Background="LimeGreen" Width="15" Height="15" Margin="2,0"Command="annot:AnnotationService.CreateHighlightCommand"> <Button.CommandParameter> <SolidColorBrush Color="#5432CD32"></SolidColorBrush> </Button.CommandParameter></Button>

I usunięcie:

<Button Command="annot:AnnotationService.ClearHighlightsCommand"> Clear Highlights</Button>

Uwaga: adnotacje są drukowane, zatem przed rozpoczęciem drukowania dobrze jest wyłączyć usługę adnotacji.

45/48

Page 46: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Przeglądanie adnotacji

Klasa AnnotationStore pozwala również przeglądać stworzone adnotacje.

IList<Annotation> annotations = service.Store.GetAnnotations();foreach (Annotation annotation in annotations){...}

Własności klasy Annotation• Id – globalny identyfikator• AnnotationType – rodzaj adnotacji• Anchors – wskazanie na adnotowany tekst (można też skorzystać z metody

GetAnchorInfo() klasy AnnotationHelper).• Cargos – wskazanie na dane użytkownika dołączone do adnotacji (np. tekst notki)

(niskopoziomowe)• Authors – kolekcja stringów identyfikujących autorów adnotacji• CreationTime – data i czas utworzenia• LastModificationTime – data i czas ostatniej modyfikacji

Własności adnotacji są tylko do odczytu, nie ma łatwego sposobu programistycznej manipulacji adnotacjami.

46/48

Page 47: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Reakcja na zmianę adnotacji

Cztery zdarzenia:• AnchorChanged (gdy adnotacja jest przenoszona)• AuthorChanged (gdy zmieniana jest informacja o autorze)• CargoChanged (gdy zmieniane są dane, np. tekst)• StoreContentChanged (gdy jest tworzona, usuwana, etc.)

Dostosowanie wyglądu notatek

Można ustawić styl:<Style TargetType="{x:Type StickyNoteControl}"> <Setter Property="Background" Value="LightGoldenrodYellow"/></Style>Więcej możliwości dadzą nam później szablony kontrolek.

47/48

Page 48: wykład 9 – Dokumenty - Instytut Informatyki UwBii.uwb.edu.pl/rybnik/dot NET/PwT.N W9.pdf · Programowanie w technologii .NET wykład 9 – Dokumenty Kontrolki Label i TextBlock

Zachowanie adnotacji w Fixed Document• W wypadku flow documents adnotacje muszą być składowane w osobnym pliku.• W wypadku fixed documents możemy przechowywać adnotacje w pliku XPS (a

nawet kilka niezależnych od siebie zbiorów adnotacji).

Uri annotationUri = PackUriHelper.CreatePartUri( new Uri("AnnotationStream", UriKind.Relative));

Package package = PackageStore.GetPackage(doc.Uri);

PackagePart annotationPart = null;if (package.PartExists(annotationUri)) annotationPart = package.GetPart(annotationUri);else annotationPart = package.CreatePart(annotationUri, "Annotations/Stream");

AnnotationStore store = new XmlStreamStore(annotationPart.GetStream());service = new AnnotationService(docViewer);service.Enable(store);

48/48