WPF の双方向機能の概要
他のどの開発プラットフォームとも異なり、WPF には双方向コンテンツ (たとえば、同じドキュメント内で左から右へ記述される情報と右から左へ記述される情報が混在している状態) の迅速な開発をサポートする多数の機能があります。 また WPF は、アラビア語やヘブライ語を扱うユーザーなど双方向機能を必要とするユーザーにとって、操作性が優れています。
以降のセクションでは、多数の双方向機能と双方向コンテンツを最適に表示した例について説明します。 この概念は C# コードまたは Microsoft Visual Basic コードに容易に適用できますが、ほとんどのサンプルでは XAML を使用します。
このトピックは、次のセクションで構成されています。
- FlowDirection
- FlowDocument
- Span 要素
- 非テキスト要素のある FlowDirection
- 数字代替
FlowDirection
WPF アプリケーションでのコンテンツのフロー方向を定義する基本プロパティが FlowDirection です。 このプロパティは 2 つの列挙値のいずれか、つまり RightToLeft または LeftToRight に設定できます。 このプロパティは、FrameworkElement を継承するすべての WPF 要素に対して使用できます。
以下の例は、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 を示す図
user interface (UI) ツリー内の要素が FlowDirection をそのコンテナーから継承します。 次の例では、TextBlock が、Window に存在する Grid 内にあります。 Window に対して FlowDirection を設定することは、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 を上書きするためには、前の例で LeftToRight に変更された 2 番目の TextBlock などの明示的な方向変更を追加する必要があります。 FlowDirection が定義されていない場合、既定の LeftToRight が適用されます。
前の例の出力を次の図に示します。
明示的に割り当てられた FlowDirection を示す図
FlowDocument
HTML、Win32、Java などの多数の開発プラットフォームは、双方向コンテンツ開発を特別にサポートしています。 HTML などのマークアップ言語では、コンテンツの作成者が任意の必要な方向にテキストを表示するために必要なマークアップを使用できます。たとえば "rtl" または "ltr" を値として解釈する HTML 4.0 タグの "dir" などです。 このタグは FlowDirection プロパティに似ていますが、FlowDirection プロパティはテキスト コンテンツのレイアウトに対する機能がより拡張されていて、テキスト以外のコンテンツでも使用できます。
WPF では、FlowDocument がテキスト、テーブル、イメージ、および他の要素の組み合わせをホストできる、柔軟性のある UI 要素となります。 以下のセクションのサンプルでは、この要素を使用します。
FlowDocument へのテキストの追加には、複数の方法があります。 単純な方法は、テキストなどのコンテンツのグループ化に使用するブロック レベル要素の Paragraph を用いることです。 サンプルでは、インライン レベルの要素にテキストを追加するために、Span と Run が使用されています。 Span は他のインライン要素のグループ化に使用されるインライン レベルのフロー コンテンツ要素で、Run は書式設定されていない一連のテキストを格納するためのインライン レベルのフロー コンテンツ要素です。 1 つの Span に、複数の Run 要素を含めることができます。
最初のドキュメント例には、いくつかのネットワーク共有名 (たとえば \\server1\folder\file.ext) がある文書が含まれます。 このネットワーク リンクがアラビア語または英語のいずれの文書にあっても、常に同じように表示する必要があります。 次の図は、アラビア語の RightToLeft ドキュメントのリンクを示します。
Span 要素の使用を示す図
テキストは RightToLeft であるため、"\" などのすべての特殊文字でテキストを右から左の順序で区切ります。 この場合、リンクが正しい順序で表示されません。したがって、この問題を解決するためにテキストを埋め込んで、フロー方向が LeftToRight の Run を個別に残す必要があります。 言語ごとに Run を作成するのではなく、頻繁には使用しない英語のテキストは大きなアラビア語の Span に埋め込むのがより良い問題の解決法です。
次の図にこれを示します。
Span 要素に埋め込んだ実行要素の使用を示す図
次の例は、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 要素でも、双方向スコープは異なると見なされます。これは、コンテナーの FlowDirection 中で Span 要素が順序付けられているということです。Span 要素内のコンテンツのみが Span の FlowDirection に従います。
次の図は、複数の TextBlock 要素のフロー方向を示します。
複数の TextBlock 要素での FlowDirection を示す図
次の例には、前の図で表示された結果を作成するために 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:lang 値を適用すると、子要素にもその属性が適用されるという XML 言語の原則も遵守されます。 前の例では、Run 要素に対しても、その最上位要素に対しても言語が定義されていないため、xml:lang の既定値 (XAML では en-US) が適用されています。 また、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" はアラビア語の 2 つのバリエーションです。 前の例は、xml:lang と FlowDirection の両方の値を定義する必要があることを示しています。
非テキスト要素のある FlowDirection
FlowDirection は、テキストのテキスト要素内でのフロー方向だけでなく、他のほぼすべての UI 要素の流れ方も定義します。 次の図は、背景を描画するために、水平 LinearGradientBrush で使用する ToolBar を示します。
左から右へのグラデーションを付けたツール バーを示す図
RightToLeft に FlowDirection を設定すると、ToolBar ボタンが右から左に整列されるだけでなく、LinearGradientBrush によりそのオフセットが右から左に移動するように調整されます。
次の図は、再構成された LinearGradientBrush を示します。
右から左へのグラデーションを付けたツール バーを示す図
RightToLeftToolBar を作成する例を次に示します。 (左から右に描画するには、ToolBar に対する FlowDirection 属性を削除します。
<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 が期待どおりに動作しない場合があります。 ここでは、そのような例外を 2 つ取り上げて説明します。
Image
Image は、イメージを表示するコントロールを表します。 XAML では、表示する Image の uniform resource identifier (URI) を定義する Source プロパティと合わせてこのコントロールを使用できます。
他の UI 要素とは異なり、Image はコンテナーから FlowDirection を継承しません。 ただし、FlowDirection が RightToLeft に明示的に設定されると、Image は左右反転して表示されます。 これは、双方向コンテンツの開発者にとって便利な機能として実装されています。場合によっては、イメージを左右反転して表示することで必要な効果が得られるためです。
次の図は、反転された Image を示します。
反転されたイメージを示す図
次の例は、Image が、それが含まれる StackPanel からの FlowDirection の継承に失敗することを示します。 メモ この例を実行するには、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:\ ドライブ上にあることを前提としています。 プロジェクト内のファイルを検索するためには、プロジェクト ファイルから C:\ドライブに .jpg をコピーするかコードを変更する必要があります。 これを行うには、Source="file://c:/ms_logo.jpg" を Source="ms_logo.jpg" に変更します。
パス
Image のほかに興味深い要素は Path です。 Pathは、接続された一連の線と曲線を描画できるオブジェクトです。 FlowDirection に関しては Image と同様に動作します。たとえば RightToLeft FlowDirection は LeftToRight を水平方向に反転したものです。 ただし、Image とは異なり、Path は FlowDirection をコンテナーから継承し、明示的に指定する必要がありません。
次の例では、3 本の線を用いて単純な矢印を描画します。 最初の矢印は、始点と終点が右側を起点として計測されるように、StackPanel から RightToLeft フロー方向を継承します。 明示的な RightToLeft FlowDirection を持つ 2 番目の矢印も右側を起点とします。 ただし、3 番目の矢印の起点は左側です。 描画の詳細については、「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 の使用方法を示す 2 つの例です。 FlowDirection は、コンテナー内の特定の方向に UI 要素を配置する他に、サーフェイス上にインクをレンダリングする InkPresenter、RadialGradientBrush、および LinearGradientBrush などの要素と合わせて使用できます。 左から右への動作を模したコンテンツに対して右から左への動作が必要な場合、またはその逆の場合には、Windows Presentation Foundation (WPF) を使用すれば可能です。
数字代替
従来から、Windows は、同じ数字をカルチャによって異なる形状で表現できるようにすると同時に、ロケールが異なってもこれらの数字の内部ストレージを統一する (たとえば、数字をごく一般的な 16 進値である 0x40 や 0x41 で格納しながら、表示は選択された言語で行う) ことによって、数字代替をサポートしてきました。
これによって、言語間での変換を行わなくてもアプリケーションが数値を処理することができます。たとえば、ローカライズされたアラビア語 Windows の Microsoft Excel スプレッドシートを開いて、アラビア語の形状の数字を表示することができますが、このスプレッドシートを Windows のヨーロッパ言語バージョンで開き同じ数字のヨーロッパ語表現を表示することもできます。 これは、コンマ区切りやパーセント記号などの他の記号でも必要です。これらの記号は、通常同じドキュメント内で数字を伴っているからです。
Windows Presentation Foundation (WPF) は引き続きこの機能を備え、代替を用いるタイミングと方法をユーザーがより広く制御できるようにこの機能を改善してゆきます。 この機能はどの言語に対しても有効ですが、アプリケーションが使用されるカルチャが多岐にわたるために特定の言語に合わせて数字の形状を設定することがアプリケーション開発者にとってに問題となる双方向コンテンツに対して特に有用です。
数字代替の Windows Presentation Foundation (WPF) での機能を制御する中核のプロパティは、Substitution 依存プロパティです。 NumberSubstitution クラスは、テキストでの数字の表示方法を指定します。 動作を定義する 3 つのパブリック プロパティがあります。 以下は、各プロパティの概要です。
CultureSource:
このプロパティは、数字のカルチャを確認する方法を指定します。 3 つの NumberCultureSource 列挙値のいずれかをとります。
Override: 数字カルチャは、CultureOverride プロパティの数字カルチャです。
Text: 数字カルチャは、テキスト ランのカルチャです。 マークアップでは、これは xml:lang、つまりエイリアスである Language プロパティ (Language または Language) です。 FrameworkContentElement から派生しているクラスの既定でもあります。 こうしたクラスには、System.Windows.Documents.Paragraph、System.Windows.Documents.Table、System.Windows.Documents.TableCell などが含まれます。
User: 数字カルチャは、現在のスレッドのカルチャです。 このプロパティは、Page、Window、および TextBlock などの FrameworkElement のすべてのサブクラスの既定です。
CultureOverride :
CultureOverride プロパティが使用されるのは Override が CultureSource プロパティに設定されている場合のみで、それ以外の場合は無視されます。 このプロパティは、数字カルチャを指定します。 既定値である null の値は、en-US として解釈されます。
代替 :
このプロパティは、実行する数字代替の種類を指定します。 次の NumberSubstitutionMethod 列挙値のいずれかをとります。
AsCulture: 数字カルチャの NumberFormatInfo.DigitSubstitution プロパティ値に基づいて代替方法が決定されます。 これは、既定の設定です。
Context: 数字カルチャがアラビアまたはペルシアのカルチャである場合に、数字がコンテキストに応じて使用されるように指定します。
European: 数字は常にヨーロッパ数字として描画されます。
NativeNational: カルチャの NumberFormat プロパティで指定された、数字カルチャに対応する国の数字を使って、数字が描画されます。
Traditional: 数字カルチャの通常の数字を使用して数字を描画することを指定します。 ほとんどのカルチャで、これは NativeNational と同じです。 ただし、NativeNational では一部のアラビア カルチャでラテン数字が表示されますが、Traditional ではすべてのアラビア カルチャでアラビア数字が表示されます。
これらの値は双方向コンテンツ開発者にとってどういった意味があるのでしょうか。 ほとんどの場合、開発者は FlowDirection と各テキスト UI 要素の言語 (たとえば Language="ar-SA") を定義するだけでよく、数字の表示は、NumberSubstitution ロジックにより、各 UI に応じて行われます。 次の例は、Windows のアラビア語版で実行されている Windows Presentation Foundation (WPF) アプリケーションでアラビア数字と英語数字を使用する方法を示します。
<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 のアラビア語版を実行している場合の、前のサンプルの出力を示します。
表示されたアラビア数字と英語数字を示す図
この場合、代わりに LeftToRight に FlowDirection を設定するとヨーロッパ数字が生成されていたため、FlowDirection が重要でした。 以下のセクションでは、ドキュメント全体で数字の表示を統一する方法について説明します。 この例では、アラビア語版 Windows で実行されていなければ、すべての数字がヨーロッパ数字として表示されます。
代替ルールの定義
実際のアプリケーションでは、プログラムでの言語設定が必要となる場合があります。 たとえば、xml:lang 属性をシステムの UI により使用されている属性と同じものに設定する場合もありますし、アプリケーション状態に応じて言語を変更する場合もあります。
アプリケーションの状態に基づいて変更を行う場合には、Windows Presentation Foundation (WPF) が備えている他の機能を使用してください。
アプリケーション コンポーネントの NumberSubstitution.CultureSource="Text" を最初に設定します。 この設定を使用すると、TextBlock などの既定値が "User" であるテキスト要素の UI から設定が取得されることはありません。
次に例を示します。
<TextBlock Name="text1" NumberSubstitution.CultureSource="Text"> 1234+5679=6913 </TextBlock> |
対応する C# コードで、Language プロパティを "ar-SA" などに設定します。
text1.Language = System.Windows.Markup.XmlLanguage.GetLanguage("ar-SA"); |
現在のユーザーの UI 言語に Language プロパティを設定する必要がある場合、次のコードを使用します。
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;
}
}
}
}
次の図は、いずれかのプログラミング言語に対するウィンドウの外観を示します。
アラビア数字を表示した図
Substitution プロパティの使用
数字代替の Windows Presentation Foundation (WPF) での機能は、テキスト要素の言語と FlowDirection の両方によって異なります。 FlowDirection が左から右の場合、ヨーロッパ数字が表示されます。 ただし、アラビア語のテキストが前にある場合、または言語が "ar" に設定されており、FlowDirection が RightToLeft の場合には、代わりにアラビア数字が描画されます。
ただし、たとえばすべてのユーザーに対してヨーロッパ数字を表示するなどの、統一されたアプリケーションを作成する必要のある場合もあります。 また、特定の Style で Table セルにアラビア数字を表示する必要のある場合もあります。 これを行う簡単な方法の 1 つは、Substitution プロパティを使用することです。
次の例で、最初の TextBlock には Substitution プロパティ セットがないため、予想されるようにアルゴリズムによってアラビア数字が表示されます。 ただし、2 番目の 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>