Partilhar via


Visão geral das funcionalidades bidirecionais no WPF

Ao contrário de qualquer outra plataforma de desenvolvimento, o WPF tem muitos recursos que suportam o desenvolvimento rápido de conteúdo bidirecional, por exemplo, dados mistos da esquerda para a direita e da direita para a esquerda no mesmo documento. Ao mesmo tempo, o WPF cria uma excelente experiência para usuários que precisam de recursos bidirecionais, como usuários que falam árabe e hebraico.

As seções a seguir explicam muitos recursos bidirecionais, juntamente com exemplos que ilustram como obter a melhor exibição de conteúdo bidirecional. A maioria dos exemplos usa XAML, embora você possa facilmente aplicar os conceitos ao código C# ou Microsoft Visual Basic.

Direção do fluxo

A propriedade básica que define a direção do fluxo de conteúdo em um aplicativo WPF é FlowDirection. Esta propriedade pode ser definida como um dos dois valores de enumeração, LeftToRight ou RightToLeft. A propriedade está disponível para todos os elementos WPF que herdam de FrameworkElement.

Os exemplos a seguir definem a direção do fluxo de um elemento TextBox.

Direção de fluxo da esquerda para a direita

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

Direção de fluxo da direita para a esquerda

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

O gráfico a seguir mostra como o código anterior é renderizado.

Gráfico que ilustra as diferentes direções de fluxo.

Um elemento dentro de uma árvore de interface do usuário (UI) herdará o FlowDirection de seu contêiner. No exemplo a seguir, o TextBlock está dentro de um Grid, que reside em um Window. Definir o FlowDirection para o Window implica defini-lo para o Grid e TextBlock também.

O exemplo a seguir demonstra a configuração FlowDirection.

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://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>

O nível superior Window tem uma RightToLeftFlowDirection, de modo que todos os elementos contidos nele também herdam a mesma FlowDirection. Para que um elemento substitua um FlowDirection especificado, ele deve adicionar uma alteração de direção explícita, como a segunda TextBlock no exemplo anterior, que muda para LeftToRight. Quando nenhum FlowDirection é definido, o LeftToRight padrão se aplica.

O gráfico a seguir mostra a saída do exemplo anterior:

Gráfico que ilustra a mudança explícita de direção do fluxo.

Documento de fluxo

Muitas plataformas de desenvolvimento, como HTML, Win32 e Java, fornecem suporte especial para o desenvolvimento de conteúdo bidirecional. Linguagens de marcação como HTML dão aos criadores de conteúdo a marcação necessária para exibir texto em qualquer direção necessária, por exemplo, a tag HTML 4.0, "dir" que usa "rtl" ou "ltr" como valores. Esta etiqueta é semelhante à propriedade FlowDirection, mas a propriedade FlowDirection funciona de forma mais avançada para a disposição de conteúdo textual e pode ser usada para conteúdos além de texto.

Elemento da interface do utilizador que pode hospedar uma combinação de textos, tabelas, imagens e outros elementos. Os exemplos nas seções a seguir usam esse elemento.

Adicionar texto a um FlowDocument pode ser feito de mais de uma maneira. Uma maneira simples de fazer isso é por meio de um Paragraph que é um elemento de nível de bloco usado para agrupar conteúdo, como texto. Para adicionar texto a elementos ao nível de linha, os exemplos usam Span e Run. Span é um elemento de fluxo de nível em linha usado para agrupar outros elementos em linha, enquanto um Run é um elemento de fluxo de nível em linha destinado a conter uma sequência de texto não formatado. Um Span pode conter vários elementos Run.

O primeiro exemplo de documento contém um documento que tem vários nomes de compartilhamento de rede; por exemplo, \\server1\folder\file.ext. Quer tenha este link de rede num documento em árabe ou inglês, quer que ele apareça sempre da mesma forma. O gráfico seguinte ilustra o uso do elemento Span e mostra o link em um documento árabe RightToLeft.

Gráfico que ilustra usando o elemento Span. FlowDocument

Como o texto é RightToLeft, todos os caracteres especiais, como "\", separam o texto em uma ordem da direita para a esquerda. Isso resulta que o link não seja exibido na ordem correta; portanto, para resolver o problema, o texto deve ser incorporado para preservar a separação e o fluxo de Run em relação a LeftToRight. Em vez de ter um Run separado para cada idioma, uma maneira melhor de resolver o problema é incorporar o texto em inglês usado com menos frequência em um Spanárabe maior.

O gráfico a seguir ilustra isso usando o elemento Run incorporado em um elemento Span:

Gráfico que ilustra o elemento Run incorporado em um elemento Span.

O exemplo a seguir demonstra o uso de elementos Run e Span em documentos.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://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>

Elementos de extensão

O elemento Span funciona como um separador de fronteira entre textos com diferentes direções de fluxo. Mesmo Span elementos com a mesma direção de fluxo são considerados como tendo escopos bidirecionais diferentes, o que significa que os elementos Span são ordenados na FlowDirectiondo contêiner, apenas o conteúdo dentro do elemento Span segue o FlowDirection do Span.

O gráfico a seguir mostra a direção do fluxo de vários elementos TextBlock.

Gráfico que ilustra blocos de texto com diferentes direções de fluxo.

O exemplo a seguir mostra como usar os elementos Span e Run para produzir os resultados mostrados no gráfico anterior.

<Page xmlns="http://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>

Nos elementos TextBlock da amostra, os elementos Span são arranjados de acordo com a FlowDirection dos seus pais, mas o texto dentro de cada elemento Span flui de acordo com a sua própria FlowDirection. Isto aplica-se ao latim e ao árabe – ou a qualquer outra língua.

Adicionando xml:lang

O gráfico a seguir mostra outro exemplo que usa números e expressões aritméticas, como "200.0+21.4=221.4". Observe que apenas o FlowDirection está definido.

Gráfico que exibe números usando apenas FlowDirection.

Os utilizadores desta aplicação ficarão desapontados com a saída, mesmo que o FlowDirection esteja correto, os números não são formados como números árabes devem ser formados.

Os elementos XAML podem incluir um atributo XML (xml:lang) que define a linguagem de cada elemento. O XAML também oferece suporte a um princípio de linguagem XML pelos quais os valores xml:lang aplicados a elementos pai na árvore são usados pelos elementos filho. No exemplo anterior, como uma linguagem não foi definida para o elemento Run ou qualquer um de seus elementos de nível superior, o xml:lang padrão foi usado, o que é en-US para XAML. O algoritmo interno de modelagem de números do Windows Presentation Foundation (WPF) seleciona números no idioma correspondente – neste caso, o inglês. Para fazer com que os números árabes sejam renderizados corretamentexml:lang precisa ser definido.

O gráfico a seguir mostra o exemplo com xml:lang adicionado.

Gráfico que ilustra números árabes que fluem da direita para a esquerda.

O exemplo a seguir adiciona xml:lang ao aplicativo.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://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>

Esteja ciente de que muitas línguas têm valores de xml:lang diferentes dependendo da região de destino, por exemplo, "ar-SA" e "ar-EG" representam duas variações do árabe. Os exemplos anteriores ilustram que você precisa definir os valores xml:lang e FlowDirection.

FlowDirection com elementos não textuais

FlowDirection define não apenas como o texto flui em um elemento textual, mas também a direção do fluxo de quase todos os outros elementos da interface do usuário. O gráfico seguinte mostra uma ToolBar que usa uma LinearGradientBrush horizontal para desenhar o seu plano de fundo com um gradiente da esquerda para a direita.

Gráfico que mostra uma barra de ferramentas com um gradiente da esquerda para a direita.

Depois de definir o FlowDirection para RightToLeft, não apenas os botões de ToolBar são organizados da direita para a esquerda, mas até mesmo o LinearGradientBrush realinha seus deslocamentos para fluir da direita para a esquerda.

O gráfico a seguir mostra o realinhamento do LinearGradientBrush.

Gráfico que mostra uma barra de ferramentas com um gradiente da direita para a esquerda.

O exemplo a seguir desenha um RightToLeftToolBar. (Para desenhá-lo da esquerda para a direita, remova o atributo FlowDirection no ToolBar.

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://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>

Exceções de Direção de Fluxo

Há alguns casos em que FlowDirection não se comporta como esperado. Esta secção abrange duas destas exceções.

Imagem

Um Image representa um controle que exibe uma imagem. Em XAML, ele pode ser usado com uma propriedade Source que define o URI (identificador uniforme de recurso) do Image a ser exibido.

Ao contrário de outros elementos da interface do usuário, um Image não herda o FlowDirection do contêiner. No entanto, se o FlowDirection estiver definido explicitamente como RightToLeft, uma Image será exibida invertida horizontalmente. Isso é implementado como um recurso conveniente para desenvolvedores de conteúdo bidirecional; porque, em alguns casos, virar horizontalmente a imagem produz o efeito desejado.

O gráfico a seguir mostra uma Imageinvertida.

Gráfico que ilustra uma imagem invertida.

O exemplo a seguir demonstra que o Image não consegue herdar o FlowDirection do StackPanel que o contém.

Observação

Você deve ter um arquivo chamado ms_logo.jpg na unidade C:\ para executar este exemplo.

<StackPanel 
  xmlns='http://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>

Observação

Incluído nos arquivos de download é um arquivo ms_logo.jpg. O código pressupõe que o arquivo .jpg não está dentro do seu projeto, mas em algum lugar na unidade C:\. Você deve copiar o .jpg dos arquivos de projeto para sua unidade C:\ ou alterar o código para procurar o arquivo dentro do projeto. Para fazer esta alteração, mude Source="file://c:/ms_logo.jpg" para Source="ms_logo.jpg".

Caminhos

Além de uma Image, outro elemento interessante é Path. Um Path é um objeto que pode desenhar uma série de linhas e curvas conectadas. Comporta-se de forma semelhante a um Image em relação ao seu FlowDirection; por exemplo, o seu RightToLeftFlowDirection é um espelho horizontal do seu LeftToRight. No entanto, ao contrário de um Image, Path herda seu FlowDirection do contêiner e não é necessário especificá-lo explicitamente.

O exemplo a seguir desenha uma seta simples usando 3 linhas. A primeira seta herda a direção do fluxo de RightToLeft do StackPanel para que seus pontos de início e fim sejam medidos a partir de uma raiz no lado direito. A segunda seta que tem uma RightToLeftFlowDirection explícita também começa no lado direito. No entanto, a terceira seta tem a sua raiz inicial no lado esquerdo. Para obter mais informações sobre desenho, consulte LineGeometry e GeometryGroup.

<StackPanel 
  xmlns='http://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>

O gráfico a seguir mostra a saída do exemplo anterior com setas desenhadas usando o elemento Path:

Gráfico que ilustra setas desenhadas usando o elemento Path.

O Image e o Path são dois exemplos de como o WPF usa FlowDirection. Além de dispor elementos da interface do usuário em uma direção específica dentro de um contêiner, FlowDirection pode ser usado com elementos como InkPresenter que renderiza tinta em uma superfície, LinearGradientBrush, RadialGradientBrush. Sempre que você precisar de um comportamento da direita para a esquerda para seu conteúdo que imite um comportamento da esquerda para a direita, ou vice-versa, o Windows Presentation Foundation (WPF) fornece esse recurso.

Substituição numérica

Historicamente, o Windows tem suportado a substituição de números permitindo a representação de diferentes formas culturais para os mesmos dígitos, mantendo o armazenamento interno desses dígitos unificado entre diferentes localidades, por exemplo, os números são armazenados em seus valores hexadecimais bem conhecidos, 0x40, 0x41, mas exibidos de acordo com o idioma selecionado.

Isso permitiu que os aplicativos processassem valores numéricos sem a necessidade de convertê-los de um idioma para outro, por exemplo, um usuário pode abrir uma planilha do Microsoft Excel em um Windows árabe localizado e ver os números em forma de árabe, mas abri-lo em uma versão europeia do Windows e ver a representação europeia dos mesmos números. Isso também é necessário para outros símbolos, como separadores de vírgula e símbolo de porcentagem, porque geralmente acompanham números no mesmo documento.

O Windows Presentation Foundation (WPF) continua a mesma tradição e adiciona mais suporte para esse recurso que permite mais controle do usuário sobre quando e como a substituição é usada. Embora esse recurso seja projetado para qualquer idioma, ele é particularmente útil em conteúdo bidirecional, onde moldar dígitos para um idioma específico geralmente é um desafio para os desenvolvedores de aplicativos devido às várias culturas em que um aplicativo pode ser executado.

A propriedade principal que controla como a substituição de números funciona no Windows Presentation Foundation (WPF) é a propriedade de dependência Substitution. A classe NumberSubstitution especifica como os números no texto devem ser exibidos. Tem três propriedades públicas que definem o seu comportamento. Segue-se um resumo de cada uma das propriedades:

CulturaFonte:

Esta propriedade especifica de que forma a cultura para números é determinada. É necessário um de três valores de enumeração NumberCultureSource.

CultureOverride:

A propriedade CultureOverride é usada somente se a propriedade CultureSource estiver definida como Override e for ignorada caso contrário. Especifica a cultura numérica. Um valor de null, o valor padrão, é interpretado como en-US.

Substituição:

Esta propriedade especifica o tipo de substituição numérica a ser executada. É necessário um dos seguintes valores de enumeração NumberSubstitutionMethod:

  • AsCulture: O método de substituição é determinado com base na propriedade NumberFormatInfo.DigitSubstitution da cultura numérica. Este é o padrão.

  • Context: Se a cultura numérica for uma cultura árabe ou persa, especifica que os dígitos dependem do contexto.

  • European: Os números são sempre apresentados como algarismos europeus.

  • NativeNational: Os números são renderizados usando os dígitos nacionais para a cultura numérica, conforme especificado pelo NumberFormatda cultura.

  • Traditional: Os números são renderizados usando os dígitos tradicionais para a cultura numérica. Para a maioria das culturas, isso é o mesmo que NativeNational. No entanto, NativeNational resulta em dígitos latinos para algumas culturas árabes, enquanto este valor resulta em dígitos árabes para todas as culturas árabes.

O que esses valores significam para um desenvolvedor de conteúdo bidirecional? Na maioria dos casos, o desenvolvedor pode precisar apenas definir FlowDirection e o idioma de cada elemento textual da interface do usuário, por exemplo, Language="ar-SA" e a lógica NumberSubstitution se encarrega de exibir os números de acordo com a interface do usuário correta. O exemplo a seguir demonstra o uso de números árabes e ingleses em um aplicativo Windows Presentation Foundation (WPF) em execução em uma versão árabe do Windows.

<Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://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>

O gráfico a seguir mostra a saída do exemplo anterior se você estiver executando em uma versão árabe do Windows com números árabes e ingleses exibidos:

Gráfico que mostra números árabes e ingleses.

A FlowDirection foi importante neste caso porque, em vez disso, definir o FlowDirection para LeftToRight teria rendido dígitos europeus. As seções a seguir discutem como ter uma exibição unificada de dígitos em todo o documento. Se este exemplo não estiver sendo executado no Windows árabe, todos os dígitos serão exibidos como dígitos europeus.

Definição de regras de substituição

Em um aplicativo real, você pode precisar definir o idioma programaticamente. Por exemplo, você deseja definir o atributo xml:lang como o mesmo usado pela interface do usuário do sistema ou talvez alterar o idioma dependendo do estado do aplicativo.

Se você quiser fazer alterações com base no estado do aplicativo, use outros recursos fornecidos pelo Windows Presentation Foundation (WPF).

Primeiro, defina o NumberSubstitution.CultureSource="Text"do componente da aplicação. O uso desta configuração garante que as definições não venham da Interface de Utilizador para elementos de texto que tenham "Utilizador" como padrão, como TextBlock.

Por exemplo:

<TextBlock
   Name="text1" NumberSubstitution.CultureSource="Text">
   1234+5679=6913
</TextBlock>

No código C# correspondente, defina a propriedade Language, por exemplo, como "ar-SA".

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

Se você precisar definir a propriedade Language para o idioma da interface do usuário atual, use o código a seguir.

text1.Language = System.Windows.Markup.XmlLanguage.GetLanguage(System.Globalization.CultureInfo.CurrentUICulture.IetfLanguageTag);

CultureInfo.CurrentCulture representa a cultura atual usada pelo thread atual em tempo de execução.

Seu exemplo XAML final deve ser semelhante ao exemplo a seguir.

<Page x:Class="WindowsApplication.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://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>

Seu exemplo final de C# deve ser semelhante ao seguinte.

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;
            }
        }
    }
}

O gráfico a seguir mostra a aparência da janela para qualquer linguagem de programação, exibindo números árabes:

Gráfico que exibe números árabes.

Usando a propriedade de substituição

A maneira como a substituição de números funciona no Windows Presentation Foundation (WPF) depende do idioma do elemento de texto e de seus FlowDirection. Se o FlowDirection for da esquerda para a direita, os dígitos europeus serão renderizados. No entanto, se for precedido por texto em árabe, ou se o idioma estiver definido como "ar" e o FlowDirection for RightToLeft, então são renderizados dígitos árabes.

Em alguns casos, no entanto, você pode querer criar um aplicativo unificado, por exemplo, dígitos europeus para todos os usuários. Ou dígitos árabes em células Table com uma Styleespecífica. Uma maneira fácil de fazer isso é usando a propriedade Substitution.

No exemplo a seguir, o primeiro TextBlock não tem a propriedade Substitution definida, portanto, o algoritmo exibe dígitos árabes conforme o esperado. No entanto, na segunda TextBlock, a substituição é definida como Europeia substituindo a substituição padrão para números árabes, e dígitos europeus são exibidos.

<Page x:Class="WindowsApplication.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://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>