Right-to-Left UI
Arabic and Hebrew are written from right to left, and their users expect the window to follow: ribbon, rulers, scroll bars and dialog boxes mirrored. TX Text Control .NET for WPF handles both levels. The direction of the text is part of the paragraph formatting, and the layout of the window follows the FlowDirection of WPF, as the TX Words sample Right To Left shows.
Paragraphs Written From Right to Left
A line in TX Text Control can mix left-to-right and right-to-left text. Which of these blocks comes first on the line is decided by the writing direction of the paragraph, the ParagraphFormat.Direction property. Its Direction values are LeftToRight, the default, and RightToLeft.
A right-to-left paragraph is right-aligned by nature, its default tab stops are right tabs measured from the right page margin, and the horizontal ruler starts at the right margin. In the ribbon, the Paragraph group of the formatting tab, shown as Home, holds the direction buttons TXITEM_RightToLeft and TXITEM_LeftToRight; the paragraph formatting dialog box has the setting too.
Bind a Toggle Button to the Direction
InputFormat.RightToLeft is the direction at the input position, or of the selected text, as a bool? that is null for a selection with both directions. The reference binds it to a ToggleButton in XAML:
<ToggleButton Height="29"
Name="buttonRightToLeft"
IsChecked="{Binding ElementName=textControl1, Path=InputFormat.RightToLeft, Mode=TwoWay}">
Right to Left
</ToggleButton>
The button shows the direction of the paragraph at the input position and changes it when clicked.
Change the Direction in Code
Selection.ChangeDirection changes all selected paragraphs, and mirrors their alignment and their left and right tab stops at the same time. Centered and justified paragraphs keep their alignment:
private void RightToLeftButton_Click(object sender, RoutedEventArgs e)
{
// Returns true when at least one paragraph was changed
bool changed = textControl1.Selection.ChangeDirection(Direction.RightToLeft);
}
Direction is in the TXTextControl namespace, so the file needs using TXTextControl;.
For justified Arabic text, ParagraphFormat.Justification can stretch lines with Kashida lines instead of, or in addition to, wider spaces: Spaces, Kashida or SpacesAndKashida. See Text and Paragraph Formatting.
Mirror the Window
Version 20.0 added a right-to-left application design to the controls of TX Text Control. In this layout:
- the
TextControlhas its vertical scroll bar at the left and zooms from the top right corner; - the built-in dialog boxes and context menus are laid out from right to left;
- the
RulerBaris a right-to-left ruler; - the
ButtonBarand theStatusBarshow their buttons and text parts from right to left.
In WPF, the TX Words sample turns this layout on with the FlowDirection of its main window. Set it in XAML on the Window element of MainWindow.xaml:
<Window x:Class="SampleApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WPF="clr-namespace:TXTextControl.WPF;assembly=TXTextControl.WPF"
FlowDirection="RightToLeft">
<!-- Ribbon, rulers, TextControl and status bar -->
</Window>
or in the constructor in MainWindow.xaml.cs, after InitializeComponent:
// Lay out the window and its content from right to left
FlowDirection = FlowDirection.RightToLeft;
Replace SampleApp with the namespace of your project.
The TX Words Sample
The sample Right To Left, in %USERPROFILE%\Documents\TX Text Control 34.0.NET for WPF\CSharp\TX Words\Right To Left, has a Right to Left button in the Application View group of its View tab. After the user confirms the message box, it stores the opposite FlowDirection in the application settings, shuts the application down and starts it again:

Its Closed handler starts the new instance with Process.Start(Application.ResourceAssembly.Location), and the constructor of the new main window assigns the stored value to FlowDirection right after InitializeComponent.
Restart the Application on .NET 8 and Later
The restart line of the sample dates from .NET Framework, where the application assembly is the .exe file and Process.Start with a file name uses the shell by default. A WPF application on .NET 8 or later is built differently: its code is in a .dll file, which a separate executable, the apphost, named like MyApp.exe, loads. Application.ResourceAssembly.Location then returns the path of the .dll. ProcessStartInfo.UseShellExecute is false by default on .NET, and without the shell Process.Start starts executables only, so the .dll path does not bring the application back.
Environment.ProcessPath, available since .NET 6, returns the path of the executable that started the running process, which is the .exe again. Use it in the Closed handler instead:
using System;
using System.Diagnostics;
private bool restartApplication = false;
private void MainWindow_Closed(object sender, EventArgs e)
{
// ProcessPath is the .exe that started this process, or null if unknown
if (restartApplication && Environment.ProcessPath is string exePath)
{
Process.Start(exePath);
}
}
The click handler of the button sets restartApplication to true and calls Application.Current.Shutdown(), as in the sample. On .NET Framework 4.8, where Environment.ProcessPath does not exist, the sample's Application.ResourceAssembly.Location works unchanged. Microsoft documents both members on Environment.ProcessPath and ProcessStartInfo.UseShellExecute.
Next Steps
- Localization and Resource Kit: the language of the user interface.
- Built-in Dialog Boxes: the dialog boxes in the mirrored layout.
- Connecting Ribbon Tabs in XAML: the ribbon of the window.
- Rulers and Status Bar: the bars that follow the direction.