Поделиться через


Общие сведения о двусторонних возможностях в WPF

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

В следующих разделах объясняются многие двунаправленные возможности, приводятся примеры, иллюстрирующие способы достижения наилучшего отображения на экране двунаправленного содержимого. Большинство образцов использует XAML, хотя принцип можно легко применить к коду C# или Microsoft Visual Basic.

В этом разделе содержатся следующие подразделы.

  • FlowDirection
  • FlowDocument
  • Элементы Span
  • FlowDirection с нетекстовыми элементами
  • Подстановка чисел

FlowDirection

Основным свойством, определяющим направление потока содержимого в приложении WPF, является FlowDirection. Этому свойству может быть присвоено одно из двух значений перечисления, LeftToRight или RightToLeft. Свойство доступно для всех элементов WPF, которые наследуют из FrameworkElement.

В следующих примерах задается направление потока элемента TextBox.

Направление потока слева направо

<TextBlock Background="DarkBlue" Foreground="LightBlue" 
   FontSize="20" FlowDirection="LeftToRight">
        This is a left-to-right TextBlock
</TextBlock>

Направление потока справа налево

<TextBlock Background="LightBlue" Foreground="DarkBlue"
   FontSize="20" FlowDirection="RightToLeft">
        This is a right-to-left TextBlock
</TextBlock>

Приведенный ниже рисунок показывает как предыдущий код визуализирует.

Пример FlowDirection

Выравнивание TextBlock

Элемент в дереве user interface (UI) будут наследовать FlowDirection из контейнера. В следующем примере TextBlock находится внутри Grid, который постоянно хранится в Window. Задание FlowDirection для Window подразумевает его задание как для Grid, так и для TextBlock.

Следующий пример демонстрирует установку FlowDirection.

<Window
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="FlowDirectionApp.Window1"
    Title="BidiFeatures" Height="200" Width="700" 
    FlowDirection="RightToLeft">

    <Grid>
      <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
      </Grid.ColumnDefinitions>
      <TextBlock Grid.Column="0" >
          This is a right-to-left TextBlock
      </TextBlock>

      <TextBlock Grid.Column="1" FlowDirection="LeftToRight">
          This is a left-to-right TextBlock
      </TextBlock>
    </Grid>
</Window>

Верхний уровень Window имеет RightToLeft FlowDirection, поэтому все элементы, содержащиеся в нем, наследуют то же FlowDirection. Чтобы переопределить заданное FlowDirection, к элементу необходимо добавить явное изменение направления, такое как второй TextBlock в предыдущем примере, который изменяется на LeftToRight. Когда не определен FlowDirection, применяется значение по умолчанию LeftToRight.

На следующем рисунке показаны выходные данные предыдущего примера.

Пример явно заданного FlowDirection

Иллюстрация направления потока

FlowDocument

Многие платформы разработки, такие как HTML, Win32 и Java, обеспечивают специальную поддержку развития двунаправленного содержимого. Языки разметки, такие как HTML, предоставляют редакторы записи необходимой разметки для отображения на экране текста в любом требуемом направлении, например тег 4.0 HTML, "dir", который принимает значения "rtl" или "ltr". Этот тег аналогичен свойству FlowDirection, но свойство FlowDirection предоставляет более прогрессивный способ доступа к текстовому содержимому макета и может быть использовано для иного чем текст содержимого.

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

Добавление текста к FlowDocument можно быть осуществлено несколькими способами. Простой способ добавить текст — сделать это через Paragraph, который является элементом блочного уровня, используемого для группировки такого содержимого, как текст. Чтобы добавить текст в элементы встроенного уровня, в примерах используются элементы Span и Run. Span является элементом поточного содержимого встроенного уровня, который используется для группировки других встроенных элементов, а Run является элементом поточного содержимого встроенного уровня, который предназначен для содержания цепочки неформатированного текста. Span может содержать несколько элементов Run.

Первый пример документа содержит документ, имеющий несколько сетевых совместно используемых имен; например \\server1\folder\file.ext. Независимо от того, есть ли эта сетевая ссылка в арабском или английском документе, она потребуется для того, чтобы появиться на том же пути. Приведенный ниже рисунок показывает ссылку в арабском документе RightToLeft.

Пример использования элемента Span

Документы с направлением потока справа-налево

Поскольку текст является RightToLeft, все специальные символы, такие как "\", разделяют текст справа налево. Эти результаты в ссылке показаны в неверном порядке, поэтому, чтобы решить проблему, текст должен быть встраиваемым, сохранить в результате, текст должен быть внедрен, чтобы сохранить отдельное Run, протекающего LeftToRight. Вместо того, чтобы иметь отдельные Run для каждого языка, лучшим способом решить проблему является внедрение наименее часто используемого английского текста в больший по размерам арабский Span.

Это проиллюстрировано на следующем рисунке.

Пример использования элемента Run, встроенного в элемент Span

Снимок экрана XamlPad

Следующий пример демонстрирует использование в документах элементов Run и Span.

<Page
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    FlowDirection="RightToLeft">

  <FlowDocument>
    <Paragraph>
      <Span FlowDirection="RightToLeft" >
        ستجد الملف هنا:
        <Run FlowDirection="LeftToRight">
           \\server1\filename\filename1.txt</Run>
        ثم باقى النص!
      </Span>
    </Paragraph>
  </FlowDocument>
</Page>

Элементы Span

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

Приведенный ниже рисунок показывает направление потока нескольких элементов TextBlock.

Пример FlowDirection в нескольких элементах TextBlock

Текстовые блоки с различными направлениями потоков

В следующем примере показано использование элементов Span и Run для получения результатов, представленных на предыдущем рисунке.

<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation">
  <StackPanel >

    <TextBlock FontSize="20" FlowDirection="RightToLeft">
      <Run FlowDirection="LeftToRight">العالم</Run>
      <Run FlowDirection="LeftToRight" Foreground="Red" >فى سلام</Run>
    </TextBlock>

    <TextBlock FontSize="20" FlowDirection="LeftToRight">
      <Run FlowDirection="RightToLeft">العالم</Run>
      <Run FlowDirection="RightToLeft" Foreground="Red" >فى سلام</Run>
    </TextBlock>

    <TextBlock FontSize="20" Foreground="Blue">العالم فى سلام</TextBlock>

    <Separator/>

    <TextBlock FontSize="20" FlowDirection="RightToLeft">
      <Span Foreground="Red" FlowDirection="LeftToRight">Hello</Span>
      <Span FlowDirection="LeftToRight">World</Span>
    </TextBlock>

    <TextBlock FontSize="20" FlowDirection="LeftToRight">
      <Span Foreground="Red" FlowDirection="RightToLeft">Hello</Span>
      <Span FlowDirection="RightToLeft">World</Span>
    </TextBlock>

    <TextBlock FontSize="20" Foreground="Blue">Hello World</TextBlock>

  </StackPanel>

</Page>

В элементах TextBlock примера, элементы Span раскладываются согласно FlowDirection их родительских элементов, но текст внутри каждого элемента Span располагается согласно своему собственному FlowDirection. Это применимо для латинского, арабского или любого другого языка.

Добавление xml:lang

Приведенный ниже рисунок показывает другой пример, использующий номера и арифметические выражения, такие как "200.0+21.4=221.4". Обратите внимание, что установлено только FlowDirection.

Пример чисел, использующих только FlowDirection

Числа с направлением потока справа-налево

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

Элементы XAML могут включать атрибут XML (xml:lang), определяющий язык каждого элемента. XAML также поддерживает принцип языка XML — значения xml:lang, примененные к родительским элементам в дереве, используются для дочерних элементов. В предыдущем примере, так как не был определен язык для элемента Run или для любого из элементов выше него, использовался язык по умолчанию xml:langen-US для XAML. Внутренний алгоритм вида чисел Windows Presentation Foundation (WPF) выбирает числа в соответствующем языке, в данном случае — английском. Для того чтобы правильно отображались арабские цифры необходимо, чтобы был задан элемент xml:lang.

На следующем рисунке показан пример, где добавлен элемент xml:lang.

Пример использования атрибута xml:lang

Арабские числа с направлением потока справа-налево

В следующем примере в приложение добавляется элемент xml:lang.

<Page
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    FlowDirection="RightToLeft">
      <FlowDocument>
         <Paragraph>
            <Span FlowDirection="RightToLeft" Language="ar-SA">
              العملية الحسابية: "200.0+21.4=221.4"
            </Span>
         </Paragraph>
      </FlowDocument>
</Page>

Необходимо помнить, что многие языки имеют различные значения xml:lang в зависимости от целевого региона, например "ar-SA" и "ar-EG" представляют собой два диалекта арабского языка. В предыдущих примерах показано, что необходимо определить как значение xml:lang, так и FlowDirection.

FlowDirection с нетекстовыми элементами

FlowDirection определяет не только перетекание текста в текстовом элементе, но также направление потока практически любого другого элемента UI. Приведенный ниже рисунок показывает ToolBar, использующую горизонтальную LinearGradientBrush для отрисовки фона.

Пример ToolBar с градиентом слева направо

Снимок экрана градиента

После установки FlowDirection на RightToLeft, не только кнопки ToolBar располагаются справа налево, но даже LinearGradientBrush перестраивает свои смещения для перетекания справа налево.

Приведенный ниже рисунок показывает перестройку LinearGradientBrush.

Пример ToolBar с градиентом справа налево

Градиент с направлением изменения цвета справа-налево

В следующем примере отрисовывается RightToLeft ToolBar. (Чтобы нарисовать его слева направо, удалите атрибут FlowDirection в ToolBar.

<Page
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml">

  <ToolBar FlowDirection="RightToLeft" Height="50" DockPanel.Dock="Top">
    <ToolBar.Background>
      <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,1">
        <LinearGradientBrush.GradientStops>
          <GradientStop Color="DarkRed" Offset="0" />
          <GradientStop Color="DarkBlue" Offset="0.3" />
          <GradientStop Color="LightBlue" Offset="0.6" />
          <GradientStop Color="White" Offset="1" />
        </LinearGradientBrush.GradientStops>
      </LinearGradientBrush>
    </ToolBar.Background>

    <Button FontSize="12" Foreground="White">Button1</Button>
    <Rectangle Width="20"/>
    <Button FontSize="12" Foreground="White">Button2</Button>
    <Rectangle Width="20"/>
    <Button FontSize="12" Foreground="White">Button3</Button>
    <Rectangle Width="20"/>
    <Button FontSize="12" Foreground="White">Button4</Button>
    <Rectangle Width="20"/>
  </ToolBar>
</Page>

Исключения FlowDirection

Существует несколько вариантов, когда FlowDirection ведет себя не так, как ожидалось. В этом разделе рассматриваются два из этих исключений.

Изображение

Image представляет элемент управления, который выводит на экран изображение. В XAML его можно использовать со свойством Source, определяющим uniform resource identifier (URI) Image для вывода на экран.

В отличие от других элементов UI, Image не наследует FlowDirection из контейнера. Однако, если FlowDirection явно задано, равным RightToLeft, то Image выводится на экран зеркально отображенным относительно горизонтали. Это реализуется как удобное средство для разработчиков двунаправленного содержимого; так как в некоторых случаях зеркальное горизонтальное отражение создает требуемый эффект.

Приведенный ниже рисунок показывает зеркально отраженное Image.

Пример зеркально отображенного изображения

Снимок экрана XamlPad

В следующем примере показано, что Image не наследует FlowDirection из StackPanel, содержащей его. Примечание   Чтобы запустить этот пример необходимо, чтобы на диске C:\ находился файл с именем ms_logo.jpg.

<StackPanel 
  xmlns='https://schemas.microsoft.com/winfx/2006/xaml/presentation' 
  FlowDirection="RightToLeft">

  <Image Source="file://c:/ms_logo.jpg" 
         Width="147" Height="50"/>
  <Separator Height="10"/>
  <Image Source="file://c:/ms_logo.jpg" 
         Width="147" Height="50" FlowDirection="LeftToRight" />
  <Separator Height="10"/>
  <Image Source="file://c:/ms_logo.jpg" 
         Width="147" Height="50" FlowDirection="RightToLeft"/>
</StackPanel>

Примечание   В загрузку включен файл ms_logo.jpg. В коде предполагается, что JPG-файл находится не внутри проекта, а в некотором другом месте на диске C:\. Необходимо скопировать JPG-файл из файлов проекта на диск C:\ или изменить код для поиска файла внутри проекта. Чтобы это сделать, измените Source="file://c:/ms_logo.jpg" на Source="ms_logo.jpg".

Пути

В дополнение к Image, другим интересным элементом является Path. Объект Path является объектом, который может рисовать последовательности соединенных прямых и кривых. Он ведет себя аналогичным образом что и Image относительно своего FlowDirection; например его RightToLeft FlowDirection является отражением относительно горизонтали его же LeftToRight. Однако, в отличие от Image, Path наследует свое FlowDirection из контейнера и не нуждается в его явном указании.

В следующем примере рисуется простая стрелка, использующая три строки. Первая стрелка наследует направление потока RightToLeft из StackPanel, таким образом, точки начала и конца отсчитываются из корня на правой стороне. Вторая стрелка, имеющая явно заданное RightToLeft FlowDirection, также начинается на правой стороне. Однако, третья стрелка начинается из корня на левой стороне. Дополнительные сведения по рисовании содержатся в LineGeometry и GeometryGroup.

<StackPanel 
  xmlns='https://schemas.microsoft.com/winfx/2006/xaml/presentation' 
  FlowDirection="RightToLeft">

  <Path Stroke="Blue" StrokeThickness="4">
    <Path.Data>
      <GeometryGroup >
        <LineGeometry StartPoint="300,10" EndPoint="350,30" />
        <LineGeometry StartPoint="10,30" EndPoint="352,30" />
        <LineGeometry StartPoint="300,50" EndPoint="350,30" />
      </GeometryGroup>
    </Path.Data>
  </Path>

  <Path Stroke="Red" StrokeThickness="4" FlowDirection="RightToLeft">
    <Path.Data>
      <GeometryGroup >
        <LineGeometry StartPoint="300,10" EndPoint="350,30" />
        <LineGeometry StartPoint="10,30" EndPoint="352,30" />
        <LineGeometry StartPoint="300,50" EndPoint="350,30" />
      </GeometryGroup>
    </Path.Data>
  </Path>

  <Path Stroke="Green" StrokeThickness="4" FlowDirection="LeftToRight">
    <Path.Data>
      <GeometryGroup >
        <LineGeometry StartPoint="300,10" EndPoint="350,30" />
        <LineGeometry StartPoint="10,30" EndPoint="352,30" />
        <LineGeometry StartPoint="300,50" EndPoint="350,30" />
      </GeometryGroup>
    </Path.Data>
  </Path>
</StackPanel>

На следующем рисунке показаны выходные данные предыдущего примера.

Пример рисования стрелок с помощью элемента Path

Пути

Image и Path являются двумя примерами того, как Windows Presentation Foundation (WPF) использует FlowDirection. По сравнению с трассировкой элементов UI в конкретном направлении внутри контейнера, FlowDirection может использоваться с такими элементами, как InkPresenter, который отображает рукописные данные на поверхности, LinearGradientBrush, RadialGradientBrush. Всякий раз, когда для содержимого требуется поведение справа налево, имитирующее поведение слева направо, или наоборот, Windows Presentation Foundation (WPF) предоставляет эту возможность.

Подстановка чисел

Исторически Windows поддерживало замену чисел посредством возможности представления различных культурных фигур для одних цифр во время сохранения внутреннего хранения этих цифр, объединенных среди различных местных специфик, например, числа хранятся в хорошо известном шестнадцатеричном формате, 0x40, 0x41, но отображаются на экране согласно выбранному языку.

Это позволяет приложениям вырабатывать цифровые величины без необходимости их конвертации из одного языка в другой, например пользователь может открыть электронную таблицу Microsoft Excel на местном арабском языке Windows и видеть числа, принявшие арабскую форму, однако откройте их в европейской версии Windows и увидите европейское исполнение тех же чисел. Это также необходимо для других символов, таких как разделительные запятые и символ процента, так как они обычно сопровождают числа в одном документе.

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

Основным свойством, контролирующем число работающих замен в Windows Presentation Foundation (WPF), является свойство зависимости Substitution. Класс NumberSubstitution определяет как отображаются на экране числа в тексте. Он имеет три общих свойств, определяющих его поведение. Ниже приведен краткий обзор каждого из свойств.

CultureSource:

Данное свойство задает, как определяется язык и региональные параметры для чисел. Оно принимает одно из трех значений перечисления NumberCultureSource.

  • Переопределение номера языка и региональных параметров является свойство CultureOverride.

  • Текст номера языка и региональных параметров — это язык и региональные параметры выполнения текста. В разметке это может быть xml:lang или его псевдоним — свойство Language (Language или Language). Кроме того, он используется по умолчанию для классов, производных от FrameworkContentElement. Такие классы содержат System.Windows.Documents.Paragraph, System.Windows.Documents.Table, System.Windows.Documents.TableCell и так далее.

  • Номер языка и региональных параметров пользователя — это язык и региональные параметры текущего потока. Это свойство используется по умолчанию для всех подклассов FrameworkElement, таких как Page, Window и TextBlock.

CultureOverride:

Свойство CultureOverride используется только если свойство CultureSource задано равным Override, а в противном случае игнорируется. Оно определяет язык и региональные параметры числа. Значение null, значение по умолчанию интерпретируются как en-US.

Substitution:

Это свойство задает тип замены числа на выполнение. Оно принимает одно из следующих значений перечисления NumberSubstitutionMethod.

  • AsCulture. Метод замены определяется на основе свойства NumberFormatInfo.DigitSubstitution языка и региональных параметров числа. Это значение по умолчанию.

  • Context. Если язык и региональные параметры числа являются арабскими или персидскими, они указывают, что цифры зависят от контекста.

  • European. Числа всегда отображаются как европейские цифры.

  • NativeNational. Числа отображаются с использованием национальных цифр языка и региональных параметров числа, как задано свойством NumberFormat языка и региональных параметров.

  • Traditional. Числа отображаются с использованием традиционных цифр для языка и региональных параметров числа. Для большинства языков и региональных параметров это то же самое, что NativeNational. Однако для некоторых арабских языков и региональных параметров значение NativeNational дает результат в виде латинских цифр, тогда как значение Traditional дает результат в арабских цифрах для всех арабских языков и региональных параметров.

Что означают эти значения для разработчика двунаправленного содержимого? В большинстве случаев разработчикам может потребоваться определить только FlowDirection и язык каждого текстового элемента, включенного в UI, например Language="ar-SA", и тогда логика NumberSubstitution будет отвечать за отображение чисел на экране, как того требует UI. В следующем примере демонстрируется использование арабских и английских чисел в приложении Windows Presentation Foundation (WPF), выполняющемся в арабской версии Windows.

<Page 
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" >
  <StackPanel>
   <TextBlock Background="LightGreen" FontSize="32" 
      Language="ar-SA" FlowDirection="RightToLeft">1+2=3</TextBlock>
   <TextBox Background="LightGreen" FontSize="32" 
      Language="ar-SA" FlowDirection="RightToLeft">1+2=3</TextBox>
   <TextBlock Background="LightBlue" FontSize="32">1+2=3</TextBlock>
   <TextBox Background="LightBlue" FontSize="32">1+2=3</TextBox>
 </StackPanel>
</Page>

На следующем рисунке показан результат предыдущего примера при выполнении в арабской версии Windows.

Пример отображения на экране арабских и английских чисел

Снимок экрана XamlPad с числами

FlowDirection был важен в этом случае, так как если вместо него задать FlowDirection как LeftToRight, то будут появляться европейские цифры. В следующих разделах обсуждаются способы получения единого отображения цифр на экране для всего документа. Если этот пример не выполняется на арабской Windows, все цифры отображаться на экране как европейские цифры.

Определение правил замены

В реальном приложении может потребоваться установить язык программными средствами. Например, требуется задать атрибут xml:lang так, чтобы он совпадал с атрибутом, который использует системный UI, или, возможно, требуется изменять язык в зависимости от состояния приложения.

Если требуется внести изменения на основании состояния приложения, проверьте использование других возможностей, предоставляемых Windows Presentation Foundation (WPF).

Сначала установите NumberSubstitution.CultureSource="Text" компонента приложения. Использование этого параметра гарантирует, что источником параметров для элементов текста, имеющих значение "User" по умолчанию, таких как TextBlock, будет не UI.

Примеры.

<TextBlock

Name="text1" NumberSubstitution.CultureSource="Text">

1234+5679=6913

</TextBlock>

В соответствующем коде C# присвойте свойству Language, например, значение "ar-SA".

text1.Language =

System.Windows.Markup.XmlLanguage.GetLanguage("ar-SA");

Если необходимо задать для свойства Language язык, который имеет UI текущего пользователя, используйте следующий код.

text1.Language =

System.Windows.Markup.XmlLanguage.GetLanguage(

System.Globalization.CultureInfo.CurrentUICulture.IetfLanguageTag);

CurrentCulture предоставляет текущие язык и региональные параметры, используемые текущим потоком во время выполнения.

Окончательный пример XAML должен быть подобен нижеследующему примеру.

<Page x:Class="WindowsApplication.Window1"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    Title="Code Sample" Height="300" Width="300"
>
    <StackPanel>
      <TextBlock Language="ar-SA" 
         FlowDirection="RightToLeft">عربى: 1+2=3
      </TextBlock>
      <TextBlock Language="ar-SA" 
         FlowDirection="RightToLeft" 
         NumberSubstitution.Substitution="European">عربى: 1+2=3 
      </TextBlock>
    </StackPanel>
</Page>

Окончательный пример C# должен быть подобен нижеследующему примеру.

namespace BidiTest
{
    public partial class Window1 : Window
    {

        public Window1()
        {
            InitializeComponent();

            string currentLanguage = 
                System.Globalization.CultureInfo.CurrentCulture.IetfLanguageTag;

            text1.Language = System.Windows.Markup.XmlLanguage.GetLanguage(currentLanguage);

            if (currentLanguage.ToLower().StartsWith("ar"))
            {
                text1.FlowDirection = FlowDirection.RightToLeft;
            }
            else
            {
                text1.FlowDirection = FlowDirection.LeftToRight;
            }
        }
    }
}

На следующем рисунке показано как выглядит окно для любого языка программирования.

Пример отображения на экране арабских чисел

Арабские числа

Использование свойства замены

Способ работы замены числа в Windows Presentation Foundation (WPF) зависит и от языка элемента текста и от его FlowDirection. Если FlowDirection установлено слева направо, то отображаются европейские цифры. Однако, если ему предшествует арабский текст, или задан язык "ar" и FlowDirection имеет значение RightToLeft, отображаются арабские цифры.

Тем не менее, в некоторых случаях может потребоваться создание единого приложения, например европейских цифр для всех пользователей. Или арабские цифры в ячейках Table с определенным Style. Просто способ добиться этого заключается в использовании свойства Substitution.

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

<Page x:Class="WindowsApplication.Window1"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    Title="Code Sample" Height="300" Width="300"
>
    <StackPanel>
      <TextBlock Language="ar-SA" 
         FlowDirection="RightToLeft">عربى: 1+2=3
      </TextBlock>
      <TextBlock Language="ar-SA" 
         FlowDirection="RightToLeft" 
         NumberSubstitution.Substitution="European">عربى: 1+2=3 
      </TextBlock>
    </StackPanel>
</Page>