Windows ui xaml textblock

Синтаксис XAML

Приложение Windows 8 разделено на программный код и разметку, потому что у каждого аспекта имеются свои преимущества. Несмотря на ограниченность разметки XAML в области сложной логики или вычислительных задач, полезно вынести в нее как можно большую часть программы. Разметка проще редактируется и дает более четкое представление о визуальной структуре страницы. Конечно, все данные в разметках являются строковыми, поэтому представление сложных объектов в разметке иногда выглядит громоздко. Так как в разметке нет конструкции цикла, стандартной для языков программирования, она также в большей степени подвержена повторениям.

Эти проблемы были учтены в синтаксисе XAML; самые важные решения рассматриваются в этой и следующих статьях. Давайте начнем обсуждение этой важнейшей темы с вопроса, который на первый взгляд не имеет к ней никакого отношения: определения градиентной кисти.

Градиентная кисть в программном коде

Свойство Background элемента Grid и свойство Foreground элемента TextBlock относятся к типу Brush. В программах, приводившихся ранее, этим свойствам задавались экземпляры класса, производного от Brush, называемого SolidColorBrush. Как было показано в предыдущей статье, вы можете создать экземпляр SolidColorBrush в коде и задать ему значение Color; в XAML это делается за вас.

SolidColorBrush — всего лишь одна из четырех доступных разновидностей кистей, как видно из следующей иерархии классов:

Только классы SolidColorBrush, LinearGradientBrush, ImageBrush, RadialGradientBrush и WebViewBrush поддерживают создание экземпляров. Как и большинство других классов, относящихся к работе с графикой, основная часть классов кистей определяется в пространстве Windows.UI.Xaml.Media, хотя WebViewBrush определяется в Windows.UI.Xaml.Controls.

Кисть LinearGradientBrush создает градиентный переход между двумя и более цветами. Допустим, вы хотите вывести текст, который у левого края окрашен в синий цвет, постепенно переходящий в красный к правому краю. Раз уж мы этим занялись, давайте создадим аналогичный градиент для свойства Background элемента Grid, но другим способом.

В нашей тестовой программе экземпляр TextBlock создается в XAML, а элементам Grid и TextBlock назначаются имена:

Конструктор в файле отделенного кода создает два отдельных объекта LinearGradientBrush, которые задаются свойству Background элемента Grid и свойству Foreground элемента TextBlock:

Кисти создаются с разными стилями инициализации свойств, но в остальном они идентичны. Класс LinearGradientBrush определяет два свойства StartPoint и EndPoint типа Point, который представляет собой структуру со свойствами X и Y, представляющими координаты точки на плоскости. Свойства StartPoint и EndPoint задаются относительно объекта, к которому применяется кисть, в стандартной оконной системе координат: значения X возрастают слева направо, а значения Y — сверху вниз. Точка (0, 0) соответствует левому верхнему углу, а точка (1, 0) — правому верхнему углу; градиент кисти направлен по воображаемой линии, соединяющей эти две точки. По умолчанию для StartPoint и EndPoint используются значения (0, 0) и (1, 1); таким образом, градиент следует из левого верхнего в правый нижний угол целевого объекта.

LinearGradientBrush также содержит свойство с именем GradientStops, которое содержит коллекцию объектов GradientStop. Каждый объект GradientStop обозначает смещение (Offset) относительно линии градиента и цвет (Color) в этом смещении.

Обычно смещения задаются в диапазоне от 0 до 1, но в особых случаях они могут выходить из диапазона кисти. LinearGradientBrush определяет дополнительные свойства, которые определяют способ вычисления градиента и способ закраски за границей наименьшего и наибольшего смещения. Результат выглядит так:

Если теперь рассмотреть возможность определения этих же кистей в XAML, неожиданно проявляются все ограничения разметки. XAML позволяет определить SolidColorBrush простым заданием цвета, но как задать свойству Foreground или Background текстовую строку, определяющую две точки с двумя и более смещениями и цветами?

Синтаксис элементов свойств

К счастью, выход существует. Как вы уже видели, для обозначения сплошной кисти SolidColorBrush в XAML обычно просто указывается цвет кисти:

Объект SolidColorBrush будет создан автоматически. Однако существует разновидность этого синтаксиса, которая позволяет более точно описать создаваемую кисть. Удалите свойство Foreground и разделите элемент TextBlock на начальный и конечный теги. В эти теги вставьте дополнительную пару из начального и конечного тегов с именем элемента и именем свойства, разделенными точкой, а в эти теги заключите объект, который нужно задать свойству:

Теперь из разметки четко видно, что свойству Foreground задается экземпляр SolidColorBrush.

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

Читайте также:  Windows no editor pak как открыть

XAML устанавливает ограничение для тегов элементов свойств: начальный тег не может содержать никакой информации. Объект, задаваемый свойству, полностью задается содержимым между начальным и конечным тегами. В следующем примере для свойства Color объекта SolidColorBrush используется вторая пара тегов элемента свойства:

При желании два других свойства TextBlock можно задать аналогичным образом:

Но никакого смысла в этом нет — для таких простых свойств синтаксис атрибутов проще и компактнее. Синтаксис элементов свойств полезен при выражении более сложных объектов — таких, как LinearGradientBrush, как показано в примере ниже:

Сначала мы разместили в тегах элементов свойств элемент LinearGradientBrush, разделенный на начальный и конечный теги. Затем задали свойства StartPoint и EndPoint в начальном теге. Обратите внимание: два свойства типа Point задаются двумя числами, разделенными пробелом. При желании эти числа можно разделить запятыми.

У LinearGradientBrush есть свойство GradientStops, которое представляет собой коллекцию объектов GradientStop, это свойство относится к типу GradientStopCollection. Затем мы добавили в коллекцию два объекта GradientStop.

Мы получили то, что хотели получить: довольно сложное свойство разметки, выраженное исключительно на уровне разметки XAML.

Свойства содержимого

Только что рассмотренный нами синтаксис создания экземпляра и инициализации LinearGradientBrush в действительности получается чуть более экстравагантным, чем реально необходимо. Возможно, вы согласитесь с этим, когда примете во внимание один простой факт: во всех файлах XAML, рассматривавшихся нами до настоящего времени, отсутствовали некоторые ключевые свойства и элементы. Рассмотрим небольшой фрагмент разметки:

Из работы с классами в коде мы знаем, что элементы TextBlock добавлены в коллекцию Children элемента Grid, а сам элемент Grid задан свойству Content элемента Page. Но где же находятся свойства Children и Content в разметке?

Что ж, при желании их можно включить. Вот как выглядят элементы свойств Page.Content и Grid.Children в том виде, в котором они могли бы присутствовать в файле XAML:

В этой разметке по-прежнему отсутствует объект UIElementCollection, заданный свойству Children элемента Grid. Его невозможно включить явно, потому что в файлах XAML могут создаваться только экземпляры элементов, имеющих открытые конструкторы без параметров, а у класса UIElementCollection такого конструктора нет.

А теперь вопрос: почему элементы свойств Page.Content и Grid.Children не обязательны в файле XAML?

Все очень просто: все классы, упоминаемые в XAML, могут иметь одно (и только одно) свойство, называемое свойством содержимого. Для этого свойства (и только для него!) теги элементов свойств не обязательны.

Свойство содержимого конкретного класса задается в виде атрибута .NET. Где-то в фактическом определении класса Panel (производным от которого является Grid) находится атрибут с именем ContentProperty. Если бы эти классы определялись в C#, это выглядело бы так:

Смысл определения прост. Каждый раз, когда парсер XAML встречает разметку следующего вида:

он проверяет атрибут ContentProperty элемента Grid и обнаруживает, что элементы TextBlock должны быть добавлены в свойство Children.

Аналогичным образом в определении класса UserControl (производным от которого является Page) свойство Content определяется как свойство содержимого:

Вы можете определять атрибут ContentProperty в ваших собственных классах. Необходимый для этого класс ContentPropertyAttribute находится в пространстве имен Windows.UI.Xaml.Markup.

К сожалению, на момент написания этих строк в документации Windows Runtime сообщается лишь то, что атрибут ContentProperty установлен для класса (для примера загляните в раздел Attributes домашней страницы класса Panel), но не указано, для какого именно свойства он установлен! Возможно, в будущем документация будет доработана, но до тех пор придется изучать примеры и экспериментировать.

К счастью, многие свойства содержимого определяются как самые удобные свойства класса. Для LinearGradientBrush свойством содержимого является GradientStops. И хотя GradientStops относится к типу GradientStopCollection, XAML не требует явного включения объектов коллекций. Ни элементы свойств LinearGradientBrush.GradientStops, ни теги GradientStopCollection не являются обязательными, поэтому запись можно упростить до следующею вида:

Трудно представить себе разметку, которая была бы проще и при этом сохраняла бы корректность синтаксиса XML. Теоретически возможно переписать программу так, чтобы все делалось в разметке XAML:

Даже с синтаксисом элементов свойств разметка читается лучше, чем версия в коде. Код наиболее четко показывает, как что-то строится. Разметка показывает готовую конструкцию. Однако при этом следует обратить внимание на одно обстоятельство. Допустим, вы определили элемент свойства для Grid с несколькими потомками:

Также можно разместить элемент свойства внизу:

Однако вы не сможете разместить одну часть содержимого до элемента свойства, а другую после:

Откуда взялся такой запрет? Проблема становится очевидной при явном включении тегов элементов свойств для свойства Children:

Получается, что свойство Children определяется дважды с двумя разными коллекциями, а это запрещено.

Читайте также:  Adobe zii для mac os

Свойство содержимого TextBlock

Как было показано ранее, элемент TextBlock позволяет задавать текст как содержимое. Однако свойством содержимого элемента TextBlock является не свойство Text, а свойство с именем Inlines типа InlineCollection — коллекции объектов Inline, или, говоря точнее, экземпляров классов, производных от Inline. Класс Inline и его производные классы находятся в пространстве имен Windows.UI.Xaml.Documents. Иерархия выглядит так:

Эти классы позволяют задавать разные виды отформатированного текста в одном элементе TextBlock. TextElement определяет Foreground и все свойства, относящиеся к шрифтам: FontFamily, FontSize, FontStyle, FontWeight (для назначения жирного начертания), FontStretch (узкое и широкое начертание для шрифтов, поддерживающих такую возможность), CharacterSpacing — и все они наследуются производными классами.

Классы Block и Paragraph в основном используются в сочетании с расширенной версией TextBlock, называемой RichTextBlock. Элемент Run — единственный класс, определяющий свойство Text, которое также является свойством содержимого Run. Все текстовое содержимое InlineCollection преобразуется в Run, кроме случаев, когда этот текст уже является содержимым Run. Объекты Run могут использоваться для явного задания различных шрифтовых свойств текстовых строк.

Класс Span определяет свойство Inlines, как и TextBlock. Это позволяет использовать вложение Span и классов, производных от него. Три потомка Span определяются как вспомогательные классы для упрощения записи. Например, класс Bold эквивалентен классу Span, у которого атрибуту FontWeight задано значение Bold.

В качестве примера рассмотрим элемент TextBlock с небольшой коллекцией Inlines, использующей вспомогательные классы с вложением:

В процессе разбора «лишние» фрагменты текста преобразуются в объекты Run, так что коллекция Inlines элемента TextBlock содержит шесть элементов: экземпляры Run, Bold, Run, Italic, Run и Bold. Коллекция Inlines первого элемента Bold содержит один объект Run, как и коллекция Inlines первого элемента Italic. Коллекция Inlines второго элемента Bold содержит объект Italic с коллекцией Inlines, содержащей объект Run.

Использование тегов Bold и Italic в TextBlock наглядно показывает, что синтаксис XAML основан на классах и свойствах, поддерживающих элементы. Тег Italic было бы невозможно вложить в тег Bold, если бы последний не содержал коллекции Inlines.

Ниже показано более обширное определение TextBlock с применением расширенных возможностей форматирования:

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

Как видите, элемент LineBreak способен произвольно разбивать строки. Теоретически класс InlineUIContainer позволяет внедрить в текст любой элемент UIElement (например, Image), но эта возможность работает только в RichTextBlock, а не в обычном TextBlock.

Text block

Text block is the primary control for displaying read-only text in apps. You can use it to display single-line or multi-line text, inline hyperlinks, and text with formatting like bold, italic, or underlined.

Is this the right control?

A text block is typically easier to use and provides better text rendering performance than a rich text block, so it’s preferred for most app UI text. You can easily access and use text from a text block in your app by getting the value of the Text property. It also provides many of the same formatting options for customizing how your text is rendered.

Although you can put line breaks in the text, text block is designed to display a single paragraph and doesn’t support text indentation. Use a RichTextBlock when you need support for multiple paragraphs, multi-column text or other complex text layouts, or inline UI elements like images.

For more info about choosing the right text control, see the Text controls article.

Examples

If you have the XAML Controls Gallery app installed, click here to open the app and see the TextBlock in action.

Create a text block

Here’s how to define a simple TextBlock control and set its Text property to a string.

Content model

There are two properties you can use to add content to a TextBlock: Text and Inlines.

The most common way to display text is to set the Text property to a string value, as shown in the previous example.

You can also add content by placing inline flow content elements in the TextBox.Inlines property, like this.

Elements derived from the Inline class, such as Bold, Italic, Run, Span, and LineBreak, enable different formatting for different parts of the text. For more info, see the Formatting text section. The inline Hyperlink element lets you add a hyperlink to your text. However, using Inlines also disables fast path text rendering, which is discussed in the next section.

Performance considerations

Whenever possible, XAML uses a more efficient code path to layout text. This fast path both decreases overall memory use and greatly reduces the CPU time to do text measuring and arranging. This fast path applies only to TextBlock, so it should be preferred when possible over RichTextBlock.

Certain conditions require TextBlock to fall back to a more feature-rich and CPU intensive code path for text rendering. To keep text rendering on the fast path, be sure to follow these guidelines when setting the properties listed here.

    Text: The most important condition is that the fast path is used only when you set text by explicitly setting the Text property, either in XAML or in code (as shown in the previous examples). Setting the text via TextBlock’s Inlines collection (such as

) will disable the fast path, due to the potential complexity of multiple formats.

  • CharacterSpacing: Only the default value of 0 is fast path.
  • TextTrimming: Only the None, CharacterEllipsis, and WordEllipsis values are fast path. The Clip value disables the fast path.
  • NoteВ В Prior to Windows 10, version 1607, additional properties also affect the fast path. If your app is run on an earlier version of Windows, these conditions will also cause your text to render on the slow path. For more info about versions, see Version adaptive code.

    • Typography: Only the default values for the various Typography properties are fast path.
    • LineStackingStrategy: If LineHeight is not 0, the BaselineToBaseline and MaxHeight values disable the fast path.
    • IsTextSelectionEnabled: Only false is fast path. Setting this property to true disables the fast path.

    You can set the DebugSettings.IsTextPerformanceVisualizationEnabled property to true during debugging to determine whether text is using fast path rendering. When this property is set to true, the text that is on the fast path displays in a bright green color.

    You typically set debug settings in the OnLaunched method override in the code-behind page for App.xaml, like this.

    In this example, the first TextBlock is rendered using the fast path, while the second is not.

    When you run this XAML in debug mode with IsTextPerformanceVisualizationEnabled set to true, the result looks like this.

    CautionВ В The color of text that is not on the fast path is not changed. If you have text in your app with its color specified as bright green, it is still displayed in bright green when it’s on the slower rendering path. Be careful to not confuse text that is set to green in the app with text that is on the fast path and green because of the debug settings.

    Formatting text

    Although the Text property stores plain text, you can apply various formatting options to the TextBlock control to customize how the text is rendered in your app. You can set standard control properties like FontFamily, FontSize, FontStyle, Foreground, and CharacterSpacing to change the look of the text. You can also use inline text elements and Typography attached properties to format your text. These options affect only how the TextBlock displays the text locally, so if you copy and paste the text into a rich text control, for example, no formatting is applied.

    NoteВ В Remember, as noted in the previous section, inline text elements and non-default typography values are not rendered on the fast path.

    Inline elements

    The Windows.UI.Xaml.Documents namespace provides a variety of inline text elements that you can use to format your text, such as Bold, Italic, Run, Span, and LineBreak.

    You can display a series of strings in a TextBlock, where each string has different formatting. You can do this by using a Run element to display each string with its formatting and by separating each Run element with a LineBreak element.

    Here’s how to define several differently formatted text strings in a TextBlock by using Run objects separated with a LineBreak.

    Here’s the result.

    Typography

    The attached properties of the Typography class provide access to a set of Microsoft OpenType typography properties. You can set these attached properties either on the TextBlock, or on individual inline text elements. These examples show both.

    Читайте также:  Tag all files windows
    Оцените статью
    XAML Controls Gallery