Строковые элементы

122

WPF предлагает большой набор строковых элементов, которые можно помещать в блочные или другие строковые элементы. Большинство из них довольно просты. Все они перечислены ниже.

Run

Содержит обычный текст. Допускает применение форматирования, хотя обычно для этого используется элемент Span. Элементы Run часто создаются неявно (например, при добавлении текста в абзац)

Span

Объединяет любое количество других строковых элементов. Обычно используется для особого форматирования части текста. Для этого элемент Run упаковывается в элемент Span, и задаются свойства элемента Span. (Можно просто поместить текст в элемент Span, a вложенный элемент Run будет создан автоматически.) Другая причина использования элемента Span — он позволяет легко найти и обработать конкретный фрагмент текста. Элемент Span аналогичен элементу <span> в языке HTML

Bold, Italic и Underline

Применяют соответственно полужирное, курсивное и подчеркнутое форматирование. Эти элементы порождены от Span. Однако обычно лучше упаковать формируемый текст в элемент span, а затем с помощью свойства Span.Style указать стиль с нужным форматом. Тогда впоследствии можно будет легко изменять характеристики форматирования, не меняя разметку документа

Hyperlink

Представляет ссылку, реагирующую на щелчок мыши, внутри потокового документа. В оконном приложении в ответ на событие Click можно выполнить действие (например, вывести другой документ). В страничном приложении можно использовать свойство NavigateUri, чтобы пользователь мог переходить к произвольной странице

LineBreak

Добавляет разрыв строки в блочный элемент. Прежде чем использовать разрыв строки, подумайте: возможно, лучше использовать большие значение Margin или Padding, чтобы увеличить промежутки между элементами

InlineUIContainer

Позволяет помещать элементы, не связанные с содержимым (наследники UIElement), туда, где должны быть строковые элементы (например, в элемент Paragraph). InlineUIContainer похож на BlockUIElement, но является строковым элементом, а не блочным

Floater и Figure

Позволяют внедрять всплывающее окошко, в котором можно вывести важную информацию, рисунок или связанное содержимое (например, рекламные сообщения, ссылки, кодовые фрагменты и т.п.)

Добавление пробелов

Как правило, пробельные символы в XML сворачиваются. Поскольку XAML основан на языке XML, в нем действуют те же правила.

Таким образом, если вставить в содержимое несколько пробелов подряд, они будут преобразованы в один пробел. Это означает, что разметка

<Paragraph>привет       всем</Paragraph>

эквивалентна следующей разметке:

<Paragraph>привет всем</Paragraph>

Обычно это поведение имеет смысл. Оно позволяет делать отступы в разметке документа с помощью символов разрыва строки и табуляции, не меняя способ интерпретации содержимого.

Знаки табуляции и разрывы строк обрабатываются так же, как и пробелы. Внутри содержимого они сворачиваются в один пробел, а по краям содержимого игнорируются.

Однако у этого правила есть одно исключение. Если пробел стоит перед строковым элементом, WPF сохраняет этот пробел. (А если перед ним несколько пробелов, WPF свернет их в один пробел.) Это означает, что можно написать следующую разметку:

<Paragraph>При встрече говорят <Bold>Привет</Bold></Paragraph>

Здесь пробел между строкой "При встрече говорят" и вложенным элементом Bold остается, что и требовалось. Однако если переписать разметку так, как показано ниже, пробел исчезнет:

<Paragraph>При встрече говорят<Bold> Привет</Bold></Paragraph>

В этом случае в пользовательском интерфейсе появится текст "При встрече говорятПривет". Между прочим, Visual Studio 2005 ошибочно игнорирует пробел в обоих примерах, если просматривать содержимое потокового документа в окне проектирования. Но в работающем приложении все станет на свои места.

Иногда бывает необходимо вставить пробел туда, где он обычно игнорируется, или включить последовательность пробелов. В этом случае понадобится атрибут xml:space со значением preserve, которое сообщает анализатору XML, что во вложенном содержимом нужно сохранять все пробельные символы:

<Paragraph xml:space="preserve">Это    очень   разреженный     текст</Paragraph>

Это решение лучше, но оно не устраняет все проблемы. Теперь, когда синтаксический анализатор XML почтительно относится к пробельным символам, уже нельзя использовать разрывы строки и символы табуляции, чтобы сделать отступ в содержимом для облегчения чтения кода. В длинных абзацах это усложнит понимание разметки. (Естественно, проблемы не будет, если разметка потокового документа генерируется другим инструментом: тогда вам все равно, как выглядит преобразованная разметка XAML.)

Поскольку атрибут xml:space применим к любому элементу, с пробелами можно обращаться более выборочно. Например, следующая разметка сохраняет пробелы только во вложенном элементе Run:

<Paragraph>
       <Run xml:space="preserve">Это    очень   разреженный</Run> текст
</Paragraph>

Элемент Floater

Элемент Floater (плавающее окошко) позволяет выделить часть содержимого из главного документа. По сути, эта часть помещается в "окошко", которое плавает где-то в вашем документе (обычно у одной из сторон документа). На рисунке ниже показан пример с одной строкой текста:

Плавающая цитата

Для его создания нужно просто поместить элемент Floater где-нибудь в другом блочном элементе (например, в абзаце). Сам элемент Floater также может содержать один или более блочных элементов. Ниже показана разметка, использованная для создания этого примера:

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

...
   
<Paragraph>Прежде чем выяснить, что это за положительные заряды ...
                <Floater Style="{StaticResource FloaterStyle}">
                    <Paragraph>Этот эффект называют эффектом Холла</Paragraph>
                </Floater>
</Paragraph>

Как правило, потоковый документ расширяет плавающее окошко так, чтобы все содержимое как раз уместилось в одной строке, а если это невозможно — чтобы содержимое полностью заняло по ширине колонку в окне документа. (В данном примере имеется только одна колонка, поэтому Floater занимает окно документа по всей его ширине.)

Если вас это не устраивает, то с помощью свойства Width можно задать ширину в не зависящих от устройства единицах. А с помощью свойства HorizontalAlignment можно определить местоположение плавающего окна: по центру, слева или справа. Ниже показано, как можно создать плавающее окошко, расположенное слева:

<Floater Style="{StaticResource FloaterStyle}" Width="220" HorizontalAlignment="Left">
                    <Paragraph>Этот эффект называют эффектом Холла</Paragraph>
</Floater>
Плавающее окошко, размещенное слева

По умолчанию плавающее окошко, используемое для элемента Floater, является невидимым. Однако для него можно задать текстурированный фон (с помощью свойства Background) или рамку (с помощью свойств BorderBrush и BorderThickness), чтобы четко отделить его содержимое от остальной части документа. Можно также использовать свойство Margin, чтобы добавить промежуток между плавающим окошком и документом, и свойство Padding, чтобы добавить промежуток между краями окошка и его содержимым.

Как правило, свойства Background, BorderBrush, BorderThickness, Margin и Padding имеются только у блочных элементов. Но они определены и в классах Floater и Figure, которые представляют строковые элементы.

Элемент Floater можно применять и для вывода рисунков. Но, как ни странно, не существует элемента вывода потокового содержимого, предназначенного для этой задачи. Поэтому элемент Image придется применять вместе с элементом BlockUIContainer или InlineUIContainer.

Здесь есть один опасный момент. При вставке плавающего окошка, заключающего в себе изображение, потоковый документ предполагает, что рисунок должен быть по ширине таким же, как и вся колонка текста. Размер находящегося внутри элемента Image будет изменен, что может привести к возникновению проблем, если придется сильно уменьшить или увеличить растровое изображение.

С помощью свойства Image.Stretch можно запретить изменение размеров изображения, хотя в этом случае плавающее окошко все равно займет всю колонку по ширине — просто вокруг рисунка останутся пустые места. Единственным подходящим решением при внедрении растрового изображения в потоковый документ является указание фиксированных размеров плавающего окошка. После этого с помощью свойства Image.Stretch можно определить, как будет меняться размер изображения в этом окошке. Вот пример:

<Paragraph>
                Это отличие состоит в том,
                <Floater Width="140" Padding="5,0" HorizontalAlignment="Right">
                    <BlockUIContainer>
                        <Image Source="testimage.jpg"/>
                    </BlockUIContainer>
                </Floater>
                что в полупроводниках можно обнаружить электрический ток...
</Paragraph>

Результат показан на рис.

Плавающее окошко с изображением

Обратите внимание, что изображение на самом деле находится в двух абзацах, но это не портит внешний вид документа. В потоковом документе текст обтекает все плавающие окошки.

Плавающее окошко с фиксированными размерами очень удобно при изменении масштаба документа. При этом изменяются и размеры плавающего окошка, после чего изображение внутри плавающего окошка может изменить свой размер (в зависимости от свойства Image.Stretch) и полностью заполнить плавающее окошко или разместиться в его центре.

Элемент Figure

Элемент Figure (рисунок) подобен Floater, однако он позволяет точнее управлять местоположением. Обычно используются плавающие окошки, которые дают WPF больше свободы в оформлении содержимого. Однако при работе со сложным документом и/или форматированием можно использовать именно рисунки, чтобы плавающие окошки не смещались при изменении размеров окна, или чтобы поместить окна в определенную позицию.

Итак, в чем же отличие класса Figure от класса Floater? Ниже описаны свойства, с которыми вам придется иметь дело. Здесь, однако, следует отметить, что многие из этих свойств (включая HorizontalAnchor, VerticalOffset и HorizontalOffset) не поддерживаются контейнером FlowDocumentScrollViewer, используемым для отображения потокового документа. Для них необходим один или несколько специальных контейнеров. Замените дескриптор FlowDocumentScrollViewer дескрипторами FlowDocumentReader, если вы хотите использовать свойства позиционирования рисунка.

Width

Задает ширину рисунка. Размеры рисунка можно задавать точно так же, как и размеры плавающего окна: в не зависящих от устройства единицах. Кроме того, размеры рисунка можно задать относительно всего окна или текущей колонки. Например, в XAML можно написать "0.25 content", чтобы создать окошко с размером 25% от ширины окна или "2 Column", чтобы создать окошко, которое по ширине будет равно двум колонкам.

Height

Задает высоту рисунка. Ее также задать можно задавать в не зависящих от устройства единицах. (Для сравнения: плавающее окошко выбирает для себя такую высоту, которая необходима, чтобы все содержимое уместилось при заданной ширине.) Если с помощью свойств Width и Height создать плавающее окно, которое окажется слишком маленьким, то часть содержимого будет отброшена

HorizontalAnchor

Заменяет свойство HorizontalAlignment класса Floater. Но кроме трех эквивалентных параметров (ContentLeft, ContentRight и ContentCenter) включает также параметры позиционирования рисунка на текущей странице (например, PageCenter) или столбце (например, ColumnCenter)

VerticalAnchor

Позволяет выровнять изображение по вертикали относительно текущей строки текста, текущей колонки или текущей страницы

HorizontalOffset и VerticalOffset

Определяют выравнивание рисунка. Эти свойства позволяют сместить рисунок от его базовой позиции.

Например, при отрицательном значении VerticalOffset рисунок будет смещен вверх на указанное количество единиц. Если с помощью этих свойств сместить рисунок от края окна, то освободившееся место будет занято текстом. (Если нужно добавить свободное место без текста у одной стороны рисунка, воспользуйтесь свойством Figure.Padding.)

WrapDirection

Определяет, как будет производиться обтекание текстом с одной стороны или с обеих сторон (с возможными пробелами) рисунка

Пройди тесты
Лучший чат для C# программистов