WPF の双方向機能の概要
他の開発プラットフォームとは異なり、WPF には、双方向コンテンツ (たとえば、同じドキュメント内に左から右へ記述されるデータと右から左へ記述されるデータが混在している状態) の迅速な開発をサポートする機能が多数用意されています。 同時に、WPF では、アラビア語やヘブライ語を話すユーザーなど、双方向機能を必要とするユーザーに優れた操作性を作成できます。
以降のセクションでは、多数の双方向機能と双方向コンテンツを最適に表示した例について説明します。 ほとんどのサンプルには XAML が使用されていますが、その概念は C# または Microsoft Visual Basic コードに簡単に適用できます。
FlowDirection
WPF アプリケーションでコンテンツのフロー方向を定義する基本的なプロパティは FlowDirection です。 このプロパティは、2 つの列挙値 LeftToRight または RightToLeft のいずれかに設定できます。 このプロパティは、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>
次の図は、前のコードがどのように表示されるのかを示します。
ユーザー インターフェイス (UI) ツリー内の要素には、そのコンテナーから FlowDirection が継承されます。 次の例では、TextBlock は、Window 内の Grid 内にあります。 Window に FlowDirection を設定することは、Grid と TextBlock にも設定することを意味します。
次に 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>
最上位の Window には RightToLeftFlowDirection があるため、その中に含まれるすべての要素にも同じ FlowDirection が継承されます。 指定された FlowDirection を要素でオーバーライドするには、前の例の 2 つ目の TextBlock のように LeftToRight に変更するという明示的な方向変更を追加する必要があります。 FlowDirection が定義されていない場合は、既定の LeftToRight が適用されます。
次の図は、前の例の出力を示しています。
FlowDocument
HTML、Win32、Java などの多数の開発プラットフォームは、双方向コンテンツ開発を特別にサポートしています。 HTML などのマークアップ言語では、コンテンツの作成者が任意の必要な方向にテキストを表示するために必要なマークアップを使用できます。たとえば、"rtl" または "ltr" を値として解釈する HTML 4.0 タグの "dir" などです。 このタグは FlowDirection プロパティに似ていますが、FlowDirection プロパティはテキスト コンテンツのレイアウト時により高度な方法で動作し、テキスト以外のコンテンツに使用できます。
UI 要素で、テキスト、テーブル、画像、その他の要素の組み合わせをホストできます。 以下のセクションのサンプルでは、この要素を使用します。
FlowDocument へのテキストの追加は、さまざまな方法で行うことができます。 その簡単な方法は、テキストなどのコンテンツをグループ化するために使用されるブロックレベルの要素である Paragraph を使用することです。 インラインレベルの要素にテキストを追加するために、このサンプルでは Span と Run を使用します。 Span は、他のインライン要素のグループ化に使用されるインラインレベルのフロー コンテンツ要素です。一方、Run は、一連の書式設定されていないテキストを含めることを目的としたインラインレベルのフロー コンテンツ要素です。 Span には、複数の Run 要素を含めることができます。
最初のドキュメント例には、いくつかのネットワーク共有名 (\\server1\folder\file.ext
など) があるドキュメントが含まれます。 このネットワーク リンクがアラビア語または英語のいずれのドキュメントにあっても、常に同じように表示する必要があります。 次の図は、Span 要素の使用方法と、アラビア語の RightToLeft ドキュメント内のリンクを示しています。
テキストは RightToLeft であるため、"\" など、すべての特殊文字で、テキストが右から左の順序で区切られます。 その結果、リンクが正しい順序で表示されなくなるため、問題を解決するには、テキストを埋め込み、フローが LeftToRight の Run を別に保持する必要があります。 この問題を解決するには、言語ごとに個別の Run を使用するのではなく、使用頻度の低い英語のテキストをより大きなアラビア語の Span に埋め込む方法が適しています。
次の図は、Span 要素に埋め込まれた Run 要素を使用してこれを示しています。
次の例は、ドキュメントでの Run および Span 要素の使用を示しています。
<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>
Span 要素
Span 要素は、フロー方向が異なるテキスト間の境界区切り記号として機能します。 同じフロー方向の Span 要素でも、双方向のスコープが異なると見なされます。つまり、Span 要素はコンテナーの FlowDirection で順序付けられ、Span 要素内のコンテンツのみが Span の FlowDirection に従います。
次の図は、複数の TextBlock 要素のフロー方向を示しています。
次の例は、Span および Run 要素を使用して、前の図に示されている結果を生成する方法を示しています。
<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>
サンプルの TextBlock 要素では、Span 要素は親の FlowDirectionに従ってレイアウトされますが、各 Span 要素内のテキストは独自の FlowDirection に従ってフローします。 これは、ラテン語やアラビア語だけでなく、他のどの言語にも当てはまります。
xml:lang の追加
次の図は、"200.0+21.4=221.4"
などの番号と算術式を使用する別の例を示します。 FlowDirection のみが設定されていることに注意してください。
このアプリケーションのユーザーは出力に失望するでしょう。FlowDirection が正しいにもかかわらず、数字の形状がアラビア数字の本来の形状ではないからです。
XAML 要素には、各要素の言語を定義する XML 属性 (xml:lang
) を含めることができます。 また、XAML では、ツリーの親要素に XML 値を適用すると、子要素にもその属性が適用されるという xml:lang
言語の原則も遵守されます。 前の例では、Run 要素またはその最上位要素に言語が定義されていないため、既定の xml:lang
(XAML の場合は en-US
) が使用されました。 Windows Presentation Foundation (WPF) の内部数字形成アルゴリズムによって、対応する言語 (この場合は英語) の数字が選択されます。 アラビア数字を正しく表示するためには、xml:lang
を設定する必要があります。
次の図は、xml:lang
を追加した例を示しています。
次の例では、アプリケーションに xml:lang
が追加されています。
<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>
多くの言語では、対象となる地域に応じて異なる xml:lang
値があります。たとえば、"ar-SA"
と "ar-EG"
はアラビア語の 2 つのバリエーションです。 前の例は、xml:lang
と FlowDirection の両方の値を定義する必要があることを示しています。
非テキスト要素のある FlowDirection
FlowDirection を使用して、テキスト要素内のテキストのフローだけでなく、他のほとんどすべての UI 要素のフロー方向も定義します。 次の図は、水平方向の LinearGradientBrush を使用して、左から右へのグラデーションを付けて背景を描画する ToolBar を示しています。
FlowDirection を RightToLeft に設定すると、ToolBar ボタンが右から左に配置されるだけでなく、LinearGradientBrush でもオフセットが右から左にフローするように再配置されます。
次の図は、LinearGradientBrush の再配置を示しています。
次の例では、RightToLeftToolBar を描画します (左から右に描画するには、ToolBar の FlowDirection 属性を削除します)。
<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>
FlowDirection の例外
FlowDirection が想定どおりに動作しない場合がいくつかあります。 ここでは、そのような例外を 2 つ取り上げて説明します。
イメージ
Image は、画像を表示するコントロールを表します。 XAML では、表示する Image の Uniform Resource Identifier (URI) を定義する Source プロパティでこれを使用できます。
他の UI 要素とは異なり、Image はコンテナーから FlowDirection を継承しません。 ただし、FlowDirection が明示的に RightToLeft に設定されている場合、Image は左右反転して表示されます。 これは、双方向コンテンツの開発者にとって便利な機能として実装されています。場合によっては、イメージを左右反転して表示することで必要な効果が得られるためです。
次の図は、反転された Image を示しています。
次の例は、Image で、それを含む StackPanel から FlowDirection を継承できないことを示しています。
注意
この例を実行するには、C:\ ドライブに ms_logo.jpg という名前のファイルが必要です。
<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>
注意
ダウンロード ファイルには、ms_logo.jpg ファイルが含まれています。 コードは、この .jpg ファイルがプロジェクト内ではなく、C:\ ドライブ上にあることを前提としています。 プロジェクト内のファイルを検索するためには、プロジェクト ファイルから C:\ドライブに .jpg をコピーするかコードを変更する必要があります。 これを行うには、Source="file://c:/ms_logo.jpg"
を Source="ms_logo.jpg"
に変更します。
パス
Image に加えて、もう 1 つの興味深い要素は Path です。 パスは、接続された一連の線と曲線を描画できるオブジェクトです。 FlowDirection に関しては、Image と同様に動作します。たとえば、RightToLeftFlowDirection は LeftToRight の水平方向のミラーです。 ただし、Image とは異なり、Path ではコンテナーから FlowDirection が継承されるので、明示的に指定する必要はありません。
次の例では、3 本の線を使用して単純な矢印を描画します。 最初の矢印では、RightToLeft のフロー方向が StackPanel から継承されているため、その始点と終点は右側のルートから測定されます。 また、明示的な RightToLeftFlowDirection がある 2 つ目の矢印も右側から始まります。 ただし、3 番目の矢印の起点は左側です。 描画の詳細については、LineGeometry と 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>
次の図は、Path
要素を使用して矢印が描画された前の例の出力を示しています。
Image と Path は、WPF に FlowDirection を使う方法の 2 つの例です。 コンテナー内の特定の方向に UI 要素をレイアウトする以外に、FlowDirection は、サーフェイスにインクをレンダリングする InkPresenter、LinearGradientBrush、RadialGradientBrush などの要素と共に使用できます。 左から右への動作を模したコンテンツに対して右から左への動作が必要な場合、またはその逆の場合はいつでも、その機能は、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 列挙値のいずれかを受け取ります。
オーバーライド:数値カルチャは、CultureOverride プロパティのカルチャです。
テキスト:数字カルチャは、テキスト ランのカルチャです。 マークアップでは、これは
xml:lang
またはそのエイリアスLanguage
プロパティ (Language または Language) になります。 また、これは FrameworkContentElement から派生したクラスの既定値です。 このようなクラスには、System.Windows.Documents.Paragraph、System.Windows.Documents.Table、System.Windows.Documents.TableCell などがあります。ユーザー:数値カルチャは、現在のスレッドのカルチャです。 このプロパティは、Page、Window、TextBlock などの FrameworkElement のすべてのサブクラスの既定値です。
CultureOverride:
CultureOverride プロパティは、CultureSource プロパティが Override に設定されている場合にのみ使用され、それ以外の場合は無視されます。 このプロパティは数字カルチャを指定します。 既定値である null
の値は、en-US として解釈されます。
Substitution:
このプロパティは、実行する数字の置換の種類を指定します。 次の NumberSubstitutionMethod 列挙値のいずれかを受け取ります。
AsCulture:置換方法は、数字カルチャの NumberFormatInfo.DigitSubstitution プロパティに基づいて決まります。 既定値です。
Context:数字カルチャがアラビアまたはペルシャのカルチャである場合に、数字がコンテキストによって異なるように指定します。
European:数字は常にヨーロッパの数字としてレンダリングされます。
NativeNational:数字は、カルチャの NumberFormat で指定されているように、数字カルチャの国番号を使用してレンダリングされます。
Traditional:数字は、数字カルチャの通常の数字を使用してレンダリングされます。 ほとんどのカルチャでは、これは NativeNational と同じです。 ただし、NativeNational の結果は、一部のアラビア カルチャではラテン数字になりますが、この値の結果は、すべてのアラビア カルチャでアラビア数字になります。
これらの値は双方向コンテンツ開発者にとってどういった意味があるのでしょうか。 ほとんどの場合、開発者は FlowDirection と各テキストの UI 要素の言語を定義するだけで済みます。たとえば、Language="ar-SA"
を指定すると、NumberSubstitution ロジックによって、正しい UI に合わせて数字が表示されます。 次の例は、Windows のアラビア語版で実行されている Windows Presentation Foundation (WPF) アプリケーションでアラビア数字と英語数字を使用する方法を示しています。
<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>
次の図は、アラビア語と英語の数字が表示されるアラビア語バージョンの Windows で、前のサンプルを実行した場合の出力を示しています。
この場合は FlowDirection を LeftToRight に設定するとヨーロッパの数字が得られるため、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");
Language
プロパティを現在のユーザーの UI 言語に設定する必要がある場合は、次のコードを使用します。
text1.Language = System.Windows.Markup.XmlLanguage.GetLanguage(System.Globalization.CultureInfo.CurrentUICulture.IetfLanguageTag);
CultureInfo.CurrentCulture は、実行時にその時点のスレッドによって使用されているその時点のカルチャを表します。
最終的な XAML 例は次の例のようになります。
<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>
最終的な 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="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>
.NET Desktop feedback