Compartir a través de


Información general sobre características bidireccionales en WPF

A diferencia de cualquier otra plataforma de desarrollo, WPF presenta numerosas características que admiten el desarrollo rápido de contenido bidireccional (por ejemplo, datos combinados de izquierda a derecha y de derecha a izquierda en el mismo documento). Al mismo tiempo, WPF crea una excelente experiencia para los usuarios que requieren características bidireccionales, como los usuarios que hablan árabe y hebreo.

En las siguientes secciones se explican muchas características bidireccionales, junto con ejemplos que muestran cómo conseguir la mejor visualización de contenido bidireccional. En la mayoría de los ejemplos se usa XAML, aunque se pueden aplicar fácilmente los conceptos al código de C# o Microsoft Visual Basic.

FlowDirection

La propiedad básica que define la dirección del flujo de contenido en una aplicación WPF es FlowDirection. Esta propiedad se puede establecer en uno de los dos valores de enumeración, LeftToRight o RightToLeft. La propiedad está disponible para todos los elementos de WPF que se heredan de FrameworkElement.

Los ejemplos siguientes establecen el flujo de dirección de un elemento TextBox.

Dirección del flujo de izquierda a derecha

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

Dirección del flujo de derecha a izquierda

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

En el gráfico siguiente se muestra cómo se representa el código anterior.

Gráfico que muestra las distintas direcciones de flujo.

Un elemento dentro del árbol de una interfaz de usuario (UI) heredará FlowDirection de su contenedor. En el ejemplo siguiente, el TextBlock está en el interior de una Grid, que reside en una Window. Establecer la FlowDirection para la Window implica establecerla también para Grid y TextBlock.

En el siguiente ejemplo se muestra el valor 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>

La Window de nivel superior tiene el valor RightToLeftFlowDirection, de modo que todos los elementos contenidos en ella heredarán el mismo FlowDirection. Para que un elemento reemplace una FlowDirection especificada, debe agregar un cambio de dirección explícito como el segundo TextBlock en el ejemplo anterior, que se cambia a LeftToRight. Cuando no se define FlowDirection, se aplica el valor predeterminado LeftToRight.

En el gráfico siguiente se muestra el resultado del ejemplo anterior:

Gráfico que muestra el cambio explícito de la dirección del flujo.

FlowDocument

Muchas plataformas de desarrollo, como HTML, Win32 y Java proporcionan una compatibilidad especial para el desarrollo de contenido bidireccional. Los lenguajes de marcado, como HTML proporcionan a los creadores de contenido el marcado necesario para mostrar texto en cualquier dirección, como la etiqueta HTML 4.0, "dir" que toma "rtl" o "ltr" como valores. Esta etiqueta es similar a la propiedad FlowDirection, pero la propiedad FlowDirection funciona de forma más avanzada para disponer el contenido de texto y puede usarse para otro contenido que no sea texto.

Es un elemento UI que puede hospedar una combinación de texto, tablas, imágenes y otros elementos. Los ejemplos de las secciones siguientes usan este elemento.

Agregar texto a un FlowDocument puede hacerse de varias maneras. Una manera sencilla de hacerlo es mediante una clase Paragraph, que es un elemento de nivel de bloque que se usa para agregar contenido como, por ejemplo, texto. Para agregar texto a los elementos de nivel en línea, los ejemplos usan Span y Run. Span es un elemento de contenido dinámico de nivel en línea que se usa para agrupar otros elementos en línea, mientras que Run es un elemento de contenido dinámico de nivel en línea destinado a contener una ejecución de texto sin formato. Un Span puede contener varios elementos Run.

El primer ejemplo de documento contiene un documento que tiene varios nombres de recursos compartidos de red; por ejemplo, \\server1\folder\file.ext. Tanto si tiene este vínculo de red en un documento en árabe como en inglés, siempre quiere que aparezca de la misma manera. En el gráfico siguiente se muestra el uso del elemento Span y se muestra el vínculo en un documento RightToLeft en árabe:

Gráfico que muestra el uso del elemento Span.

Dado que el texto está en orden RightToLeft todos los caracteres especiales, como "\", separan el texto en orden de derecha a izquierda. En consecuencia, el vínculo no se muestra en el orden correcto. Por lo tanto, para solucionar el problema, se debe insertar el texto para conservar un elemento Run fluyendo en el orden LeftToRight. En lugar de tener un elemento Run independiente para cada idioma, una mejor manera de resolver el problema es insertar el texto en inglés usado con menos frecuencia en un elemento Span en árabe de mayor tamaño.

En el gráfico siguiente se muestra esto mediante el elemento Run incrustado en un elemento Span:

Gráfico que ilustra el elemento Run insertado en un elemento Span.

En el ejemplo siguiente se muestra el uso de elementos Run y Span en 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 Span

El elemento Span funciona como un separador de límite entre textos con diferentes direcciones de flujo. Se considera que incluso los elementos Span con la misma dirección de flujo tienen ámbitos bidireccionales diferentes, lo que significa que los elementos Span se ordenan en el valor FlowDirection del contenedor; solo el contenido dentro del elemento Span sigue el valor FlowDirection de Span.

El gráfico siguiente muestra la dirección del flujo de varios elementos TextBlock.

Gráfico que ilustra bloques de texto con diferentes direcciones de flujo.

El ejemplo siguiente muestra cómo usar los elementos Span y Run para producir los resultados mostrados en el 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>

En los elementos TextBlock del ejemplo, los elementos Span se disponen de acuerdo con el valor FlowDirection de sus elementos primarios, pero el texto dentro de cada elemento Span fluye de acuerdo a su propio valor FlowDirection. Esto es aplicable a los idiomas latín y árabe, o a cualquier otro idioma.

Agregar xml:lang

En el gráfico siguiente se muestra otro ejemplo que usa números y expresiones aritméticas, como "200.0+21.4=221.4". Observe que solo está establecido el valor FlowDirection.

Gráfico que muestra números usando solo FlowDirection.

El resultado decepcionará a los usuarios de esta aplicación: a pesar de que la propiedad FlowDirection es correcta, los números no tienen el formato de números árabes.

Los elementos XAML pueden incluir un atributo XML (xml:lang) que define el idioma de cada elemento. XAML también admite un principio de idioma XML, por el cual los elementos secundarios usan los valores de xml:lang que se aplican a los elementos primarios en el árbol. En el ejemplo anterior, dado que no se definió un idioma para el elemento Run ni ninguno de sus elementos de nivel superior, se usó xml:lang, que es en-US para XAML. El algoritmo de forma de números interno de Windows Presentation Foundation (WPF) selecciona los números en el idioma correspondiente (en este caso, inglés). Para que los números árabes se representen correctamente, es necesario establecer xml:lang.

El siguiente gráfico muestra el ejemplo con xml:lang agregado.

Gráfico que ilustra números árabes que fluyen de derecha a izquierda.

En el ejemplo siguiente, se agrega el atributo xml:lang a la aplicación.

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

Tenga en cuenta que muchos idiomas tienen distintos valores xml:lang en función de la región de destino. Por ejemplo, "ar-SA" y "ar-EG" representan dos variaciones de árabe. Los ejemplos anteriores muestran que es necesario definir ambos valores: xml:lang y FlowDirection.

FlowDirection con elementos no textuales

FlowDirection define no solo cómo fluye el texto en un elemento textual, sino también la dirección de flujo de prácticamente cualquier otro elemento de UI. En el gráfico siguiente se muestra una ToolBar que usa un LinearGradientBrush horizontal para dibujar su fondo con un degradado de izquierda a derecha.

Gráfico que muestra una barra de herramientas con un degradado de izquierda a derecha.

Después de establecer el valor FlowDirection en RightToLeft, no solo se ordenan los botones de ToolBar de derecha a izquierda; LinearGradientBrush también vuelve a alinear sus desplazamientos para que fluyan de derecha a izquierda.

El siguiente gráfico muestra la realineación de LinearGradientBrush.

Gráfico que muestra una barra de herramientas con un degradado de derecha a izquierda.

El ejemplo siguiente dibuja una RightToLeftToolBar. (Para dibujarlo de izquierda a derecha, elimine el atributo FlowDirection en 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>

Excepciones de FlowDirection

Hay unos pocos casos en los que FlowDirection no funciona como está previsto. En esta sección se describen dos de estas excepciones.

Imagen

Image representa un control que muestra una imagen. En XAML, se puede usar con una propiedad Source que define el identificador uniforme de recursos (URI) de la Image que se va a mostrar.

A diferencia de otros elementos de UI, una Image no hereda el valor FlowDirection del contenedor. Sin embargo, si FlowDirection se establece explícitamente en RightToLeft, una Image se muestra volteada horizontalmente. Se implementa como una práctica característica para los desarrolladores de contenido bidireccional, porque el volteo horizontal de la imagen muestra el efecto deseado en algunos casos.

El siguiente gráfico muestra una Image volteada.

Gráfico que muestra una imagen volteada.

En el ejemplo siguiente se muestra que Image no ha podido heredar FlowDirection del StackPanel que lo contiene.

Nota

Debe tener un archivo denominado ms_logo.jpg en la unidad C:\ para ejecutar este ejemplo.

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

Nota

En los archivos de descarga se incluye un archivo ms_logo.jpg. En el código, se supone que el archivo .jpg no está dentro del proyecto, sino en alguna ubicación de la unidad C:\. Debe copiar el archivo .jpg de los archivos del proyecto en la unidad C:\ o cambiar el código para buscar el archivo dentro del proyecto. Para hacerlo, cambie Source="file://c:/ms_logo.jpg" por Source="ms_logo.jpg".

Paths

Además de una Image, otro elemento interesante es Path. Patch es un objeto que puede dibujar una serie de líneas y curvas conectadas. Se comporta de manera similar a una Image en relación a su FlowDirection; por ejemplo, su RightToLeftFlowDirection es un reflejo horizontal de su valor LeftToRight. Sin embargo, a diferencia de una Image, Path hereda su FlowDirection del contenedor y no es necesario especificarlo de forma explícita.

En el ejemplo siguiente se dibuja una flecha simple mediante 3 líneas. La primera flecha hereda la dirección del flujo de RightToLeft de StackPanel, de modo que sus puntos de inicio y fin se miden a partir de la raíz del lado derecho. La segunda flecha, que tiene un RightToLeftFlowDirection explícito, también empieza en el lado derecho. Sin embargo, la tercera flecha tiene su raíz de inicio en el lado izquierdo. Para obtener más información sobre el dibujo, consulte LineGeometry y 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>

En el gráfico siguiente se muestra el resultado del ejemplo anterior con flechas dibujadas mediante el elemento Path:

Gráfico que muestra las flechas dibujadas mediante el elemento Path.

Image y Path son dos ejemplos de cómo WPF usa FlowDirection. Además de diseñar elementos de interfaz de usuario en una dirección específica dentro de un contenedor, FlowDirection se puede usar con elementos como InkPresenter, que representa la entrada de lápiz en una superficie, LinearGradientBrush, RadialGradientBrush. Siempre que necesite un comportamiento de derecha a izquierda para contenido que imite un comportamiento de izquierda a derecha, o viceversa, Windows Presentation Foundation (WPF) proporciona esa funcionalidad.

Sustitución de números

Históricamente, Windows admite la sustitución de números, para lo cual permite la representación de formas culturales diferentes de los mismos dígitos, al mismo tiempo que mantiene el almacenamiento interno de estos dígitos unificado en diferentes configuraciones regionales. Por ejemplo, los números se almacenan en sus valores hexadecimales conocidos, 0x40, 0x41, pero se muestran de acuerdo con el idioma seleccionado.

Esto permite a las aplicaciones procesar valores numéricos sin necesidad de convertirlos de un idioma a otro. Por ejemplo, un usuario puede abrir una hoja de cálculo de Microsoft Excel en un sistema Windows árabe localizado y ver los números en árabe, y abrirlo en una versión europea de Windows y ver una representación europea de los mismos números. Esto también es necesario para otros símbolos, como el símbolo de porcentaje y los separadores de coma, porque suelen acompañar a los números del mismo documento.

Windows Presentation Foundation (WPF) continúa con la tradición y agrega más compatibilidad con esta característica, que aumenta el control del usuario sobre cuándo y cómo usar la sustitución. Aunque esta característica está diseñada para cualquier idioma, es especialmente útil en el contenido bidireccional, donde definir los dígitos de un idioma concreto normalmente constituye un desafío para los desarrolladores de aplicaciones debido a las distintas referencias culturales en las que se puede ejecutar una aplicación.

La propiedad principal que controla el funcionamiento de la sustitución de números en Windows Presentation Foundation (WPF) es la propiedad de dependencia Substitution. La clase NumberSubstitution especifica cómo se muestran los números en el texto. Tiene tres propiedades públicas que definen su comportamiento. A continuación se muestra un resumen de cada una de las propiedades:

CultureSource:

Esta propiedad especifica cómo se determina la referencia cultural para los números. Toma uno de tres valores de enumeración NumberCultureSource.

CultureOverride:

La propiedad CultureOverride solo se usa si la propiedad CultureSource se establece en Override y se ignora. Especifica la referencia cultural de número. Un valor de null, que es el valor predeterminado, se interpreta como en-US.

Substitution:

Esta propiedad especifica el tipo de sustitución de números que se va a realizar. Toma uno de los siguientes valores de enumeración NumberSubstitutionMethod:

  • AsCulture: el método de sustitución se determina en función de la propiedad NumberFormatInfo.DigitSubstitution de la referencia cultural de número. Este es el valor predeterminado.

  • Context: si la referencia cultural de número es árabe o persa, especifica que los dígitos dependen del contexto.

  • European: los números siempre se representan como dígitos europeos.

  • NativeNational: los números se representan mediante los dígitos nacionales de la referencia cultural de número, como lo especifica el NumberFormat de la referencia cultural.

  • Traditional: los números se representan mediante dígitos tradicionales para la referencia cultural de número. En la mayoría de las referencias culturales, es igual que NativeNational. Sin embargo, NativeNational puede generar dígitos latinos en algunas referencias culturales árabes, mientras con este valor se obtienen dígitos árabes para todas las referencias culturales árabes.

¿Qué significan esos valores para un desarrollador de contenido bidireccional? En la mayoría de los casos, el desarrollador podría tener que definir solo la propiedad FlowDirection y el idioma de cada elemento textual de UI, por ejemplo Language="ar-SA", y la lógica NumberSubstitution se encarga de mostrar los números con la UI correcta. En el ejemplo siguiente se muestran números árabes e ingleses en una aplicación de Windows Presentation Foundation que se ejecuta en una versión árabe de 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>

En el gráfico siguiente se muestra el resultado del ejemplo anterior si se ejecuta en una versión árabe de Windows con números en árabe e inglés:

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

En este caso, el valor FlowDirection era importante porque establecer FlowDirection en LeftToRight en su lugar habría generado dígitos europeos. En las secciones siguientes se explica cómo conseguir una presentación unificada de dígitos en todo el documento. Si este ejemplo no se ejecuta en una versión árabe de Windows, todos los dígitos se mostrarán como dígitos europeos.

Definición de reglas de sustitución

En una aplicación real, es posible que tenga que establecer el idioma mediante programación. Por ejemplo, quiere establecer el atributo xml:lang para que coincida con el que usa la UI del sistema, o quizás cambiar el idioma en función del estado de la aplicación.

Si quiere realizar cambios según el estado de la aplicación, use otras características que proporciona Windows Presentation Foundation (WPF).

En primer lugar, establezca el valor NumberSubstitution.CultureSource="Text" del componente de la aplicación. Este valor garantiza que la configuración no procede de la UI para los elementos de texto que tienen "User" como valor predeterminado, como TextBlock.

Por ejemplo:

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

En el código de C# correspondiente, establezca la propiedad Language, por ejemplo, en "ar-SA".

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

Si necesita establecer la propiedad Language en el idioma de la UI del usuario actual, use el código siguiente.

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

CultureInfo.CurrentCulture representa la referencia cultural actual usada por el subproceso actual en tiempo de ejecución.

El ejemplo de XAML final debería ser similar al ejemplo siguiente.

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

El ejemplo de C# final debería ser similar al siguiente.

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

El gráfico siguiente muestra el aspecto de la ventana para cualquier lenguaje de programación con números árabes:

Gráfico que muestra números árabes.

Uso de la propiedad Substitution

La forma en que la sustitución de números funciona en Windows Presentation Foundation (WPF) depende tanto del idioma del elemento de texto como de su valor de FlowDirection. Si el valor FlowDirection es de izquierda a derecha, se representan los dígitos europeos. Sin embargo, si está precedido por texto en árabe, o el idioma está establecido en "ar" y el valor FlowDirection es RightToLeft, en su lugar se representan dígitos en árabe.

En algunos casos, sin embargo, es posible que quiera crear una aplicación unificada, como, por ejemplo, dígitos europeos para todos los usuarios. O dígitos en árabe en celdas de Table con un Style específico. Una manera fácil de hacerlo es mediante la propiedad Substitution.

En el ejemplo siguiente, el primer TextBlock no tiene la propiedad Substitution establecida, de modo que el algoritmo muestra dígitos en árabe como se esperaba. Sin embargo, en el segundo TextBlock, la sustitución está establecida en europeo, lo que invalida la sustitución predeterminada de números árabes y se muestran dígitos europeos.

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