-
Really that means two things:
1) Silverlight 4, now displays Arabic properly. On earlier versions, the characters were reversed and appeared in their isolated form. Now we finally have Arabic letters combined and shaped properly.
2) Second, we have a new property specific for Arabic display. “FlowDirection” We kept a consistent behavior with WPF FlowDirection property. There are two values, FlowDirection = “RightToLeft” and FlowDirection=”LeftToRight” (as default). To host Arabic Silverlight controls, you need to set FlowDirection =”RightToLeft” You can set FlowDirection on the root level and it would be inherited in your other controls.
This is a sample of a Silverlight Arabic sample to display a welcome string and the calendar control:
<UserControl x:Class="SilverlightSampleApp.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400" xmlns:dataInput="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.Input" xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
FlowDirection="RightToLeft">
<Grid x:Name="LayoutRoot" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="188*" />
<ColumnDefinition Width="212*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="74*" />
<RowDefinition Height="226*" />
</Grid.RowDefinitions>
<dataInput:Label Margin="10" Content =" مرحباً بكم." FontSize="22" />
<controls:DatePicker Grid.Row="1" Grid.Column="1" Margin="40" Name="datePicker1" VerticalAlignment="Top" Width="120" />
</Grid>
</UserControl>
Want to see a nice video in action, then check http://silverlight.net/learn/videos/all/bidi-right-to-left/
Check the details below on how to download and start testing Silverlight 4 Beta.
-
This is a truly exciting time to see the beta of Silverlight 4. Finally after 3 versions we have Arabic support in Silverlight. This is really great news and a great chance for Arabic Silverlight users. I would like people to try it out and download it and give it a try. This is our chance to evaluate the Arabic support early and give our feedback. You can check the official website Silverlight 4 Beta : The Official Microsoft Silverlight Site.
For an interesting demo you can watch Karen’s Silverlight session during PDC SilverLight 4 Overview. At around 33 mins you’ll see Mona chatting in Arabic with Karen J
What you need to start try it? These are your tools:
· First, you need VS 2010 Beta 2, for a quick download I suggest using the Visual Web Developer Express (.EXE)
· Next, Download Silverlight 4 Tools.
How to submit your feedback?
You can log your bugs, issues and even suggestions through http://connect.microsoft.com/VisualStudio
Log the issues under Silverlight 4 beta. Include in your title the word “BIDI”, so we can better track Arabic\bidi issues.
In the following days I’ll have some posts on Arabic Silverlight support. So check back for more info.
-
To get you started I wrote this simple sample that uses the Visual Studio International Pack 2.0 (VSIntlPack2), numeric conversion module to convert the numbers to Arabic words. This is an easy walk through to use the numeric conversion. First download the VS IntlPack2 from the link provided in my previous post:
1) I created a simple WinForm application.
2) Add Reference to “InternationNumericFormatter.dll” library.
3) In the WinForm designer:
a. Add a TextBox1: to accept the user numbers.
b. Add a Label1: to display the output of the numeric conversion module.
4) Add an event to handle the TextBox1.TextChanged.. and double click to go the code view
5) In the code:
a. First, add reference to the library and we’ll use the System.Globalization namespace so we can add it as well:
VB:
Imports Microsoft.International.Formatters
Imports System.Globalization
C# :
using Microsoft.International.Formatters;
using System.Globalization;
b. Add this code in the textbox1_TextChanged:
VB Code:
Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged
Dim Value As Double
Dim ArabicCulture As New CultureInfo("ar")
If Double.TryParse(TextBox1.Text, Value) Then
If Value <= 999999999999999999 Then
Label1.Text = InternationalNumericFormatter.FormatWithCulture("L", Value, ArabicCulture, ArabicCulture)
Else
Label1.Text = "The number is out of range"
End If
Else
Label1.Text = ""
End If
End Sub
C# Code:
private void textBox1_TextChanged(object sender, EventArgs e)
{
Double Value;
if (Double.TryParse(textBox1.Text, out Value))
{
if (Value <= 9999999999999999999)
label1.Text = InternationalNumericFormatter.FormatWithCulture("L", Value, null, new CultureInfo("ar"));
else
label1.Text = "The number is out of range";
}
else
label1.Text = "";
}
6) Build and run your app… and you can type the numbers in the textbox and see the words in the label.
I hope you enjoyed this walkthrough!
-
وأخيراً، تم إصدار Visual Studio International Feature Pack 2.0 , ويحتوي على مجموعة من عناصر التحكم فضلا عن مجموعة من المكتبات فئة مصمم لمساعدة المطورين .NET على إنشاء تطبيقات العالم الجاهزة.
يحتوي هذا الإصدار على العديد من الميزات و الخصائص لدول شرق أسيا. تمت إضافة دعم إضافي التنسيق الرقمي باللغة العربية في الإصدار 2.0.يمكنك الآن استخدام مكتبة التنسيق الرقمي تفقيط الأرقام إلى حروف باللغة العربية.
يمكنك تنزيل الإصدار من موقع Microsoft من: http://www.microsoft.com/downloads/details.aspx?FamilyID=7d1df9ce-4aee-467f-996e-bec826c5daa2&displaylang=ar
At last the Visual Studio International Feature Pack 2.0 has released. It contains a set of controls as well as a set of class libraries designed to help .NET developers create world-ready applications.
This release has many features and libraries for East-Asian countries. In this release we also have new support of converting numbers to letter for Arabic.
You can download this release from Microsoft download site: http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=7d1df9ce-4aee-467f-996e-bec826c5daa2
-
I had a customer question about how to use FlowDocumentReader in WPF, for Arabic text. I thought this was a good opportunity to share with you this short sample.
This is a FlowDocumentReader that displays an Arabic FlowDocument. I included diacritics in the strings to make it more illustrative. To make sure that your document is displayed properly you need to set the language of the document. In my sample , I set the language to Arabic-Egypt. This will fix the display, beside setting the proper digit substitution or number substitution. But to make our scenario more complex, I decided to use European number substation , to make use of this ability. I set NumberSubstitution.Substitution="European", but in most cases I would leave the default behavior.
I hope you enjoy this sample:
<FlowDocumentReader FlowDirection="RightToLeft" Language="ar-EG" NumberSubstitution.Substitution="European"
Margin="10" BorderBrush="Gray" BorderThickness="2">
<FlowDocument ColumnWidth="400" IsOptimalParagraphEnabled="True" IsHyphenationEnabled="True" >
<Section FontSize="18">
<Paragraph>
<Bold>اعلن</Bold> المسؤولون في وكالةِ الفضاءَ الامريكيةَ ناسا انْ اطلاقْ مكوكَ الفضاءَ انديفّور الغي بسبب تسرب للهيدروجين.
<Figure Width="250" Height="50" Background="Bisque" HorizontalAnchor="PageLeft" HorizontalOffset="100" VerticalOffset="20">
<Paragraph FontStyle="Italic" Foreground="Green">
ناسا تُلغي اطِلاق مكّوك فضاء
</Paragraph>
</Figure>
</Paragraph>
<Paragraph>
كان من المقرر اطلاق انديفور من قاعدة كيب كانيفرال وعلى متنه سبعة رواد فضاء في السابعة و17 دقيقة صباح اليوم بالتوقيت المحلي،
لكن اطلاقه الغي قبل الموعد بساعات قليلة.
</Paragraph>
</Section>
</FlowDocument>
</FlowDocumentReader>
-
Visual Studio International Feature Pack 2.0 Beta has some great features for our international customers. There are many features for our East Asian customers in addition to a feature for our Arabic customers. I had many customer requests to display numbers in written Arabic form. The Numeric Formatting Library provides a class library for formatting numeric data into 5 languages. Arabic is a new language, in version 2. Arabic download page is: http://www.microsoft.com/downloads/details.aspx?displaylang=ar&FamilyID=188ae407-8db0-4df2-9789-70f7ef3410b9
English page is: http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=188ae407-8db0-4df2-9789-70f7ef3410b9
Please check it out and give us feedback.
-
This is a very common case…. There are so many application that needs to enter numbers in a text box… but what is the best method to do that.
First, you need to validate the number as the user enters it in the text box:
Depending on your required type you can use the .TryParse to check the validity of the input.
This is a small code sample,
Double.TryParse(textBox1.Text,NumberStyles.Any,CultureInfo.CurrentCulture,out value)
This function returns a bool, test your bool and if cann’t be parsed then raise a validation error or disable the user from proceeding.
The default is to use CultureInfo.CurrentCulture, so, when you use the sample on machine with English or Arabic local, it would accept the thousand separator (,)… when you work on a machine with French locale it wouldn’t accept the thousand separator (,).
In the case you need to specify a different formatting of the numbers… for example, accept only number formatting according to the French (France locale). Then you can specify the correct culture.
For example,
Double.TryParse(textBox1.Text,NumberStyles.Any, new CultureInfo(fr-FR”),out value)
This way you can verify the correct the number formatting before you accept the numbers in a textbox.
-
It’s a sign!... I need to write a new blog post … I skipped last month because I had so much work ... this month I also have too much work… so, what should I do? …. The only answer happened this morning.
This morning, I have exchange connectivity issues and I can’t access my emails J... I tried to access my email from both machines, and then I tried to connect through OWA but no luck. Finally I went to our IT website and found that my email exchange server is having difficulties. I’ve been worried about my emails that I sent yesterday and people’s reply… but now, it’s out of my hand… I’ll sit and blog until I get my email workingJ
I just came back from a visit to Egypt where I met with customer, Microsoft Egypt team, MVPs and MSPs. I sat down to gather feedback and share our plans. It was a blast, people are so excited about our products Visual Studio, Team System, Silverlight. The MSP s in Egypt were so excited and eager to know more about how to start their careers… their eyes were glowing brilliantly as they talked about their future… It was so refreshing to see such an excited bunch J
So I didn’t speak about Arabic development this time… but I’ll do soon… so see you around
-
I had a customer question about using Um Al Qura calendar in SQL Server. There is an existing implementation in the .NET Framework, starting from version 2.0 of UmAlquraCalendar. So what you need to do is define a new CLR type based on the UmAlQuraCalendar and then use it in SQL server, either define fields or to convert the CLR types that you can use in the code.
First step, create a user-defined type to be used in SQL server. This is a sample code to show how to create and use a CLR data type.
If you have Visual Studio, then follow these steps:
- Create a new Database project in the Visual C# language nodes.
- Add a reference to the SQL Server database that will contain the user-defined data types.
- Add a User-Defined Type class.
- Copy this code that implements the UmAlQura Calendar :
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Globalization;
[Serializable]
[SqlUserDefinedType(Format.Native, IsByteOrdered = true)]
public struct UmAlQuraDate : INullable
{
private long dtTicks;
private bool isNull;
// Calendar object used for all calendar-specific operations
private static readonly UmAlQuraCalendar s_calendar =
new UmAlQuraCalendar();
// For correct formatting we need to provide a culture code for
// a country that uses the Um Al Qura calendar: Saudi Arabia.
private static readonly CultureInfo ci =
new CultureInfo("ar-SA", false);
// get a null instance
public static UmAlQuraDate Null
{
get
{
UmAlQuraDate dt = new UmAlQuraDate();
dt.isNull = true;
return dt;
}
}
public bool IsNull
{
get
{
return this.isNull;
}
}
public UmAlQuraDate(long ticks)
{
isNull = false;
dtTicks = ticks;
}
public UmAlQuraDate(DateTime time)
: this(time.Ticks)
{
}
public static UmAlQuraDate Parse(SqlString s)
{
if (s.IsNull) return Null;
DateTime t = DateTime.Parse(s.Value);
return new UmAlQuraDate(t);
}
public static UmAlQuraDate ParseArabic(SqlString s)
{
if (s.IsNull) return Null;
DateTime t = DateTime.Parse(s.Value, ci);
return new UmAlQuraDate(t);
}
public static UmAlQuraDate FromSqlDateTime(SqlDateTime d)
{
if (d.IsNull) return Null;
return new UmAlQuraDate(d.Value);
}
public static UmAlQuraDate Now
{
get
{
return new UmAlQuraDate(DateTime.Now);
}
}
public DateTime DateTime
{
get { return new DateTime(this.dtTicks); }
}
public SqlDateTime ToSqlDateTime()
{
return new SqlDateTime(this.DateTime);
}
public override String ToString()
{
return this.DateTime.ToString(ci);
}
public String ToStringUsingFormat(String format)
{
return this.DateTime.ToString(format, ci);
}
public int Year
{
get
{
return s_calendar.GetYear(this.DateTime);
}
}
public int Month
{
get
{
return s_calendar.GetMonth(this.DateTime);
}
}
public int Day
{
get
{
return s_calendar.GetDayOfMonth(this.DateTime);
}
}
public UmAlQuraDate AddYears(int years)
{
return new
UmAlQuraDate(s_calendar.AddYears(this.DateTime, years));
}
public UmAlQuraDate AddDays(int days)
{
return new
UmAlQuraDate(s_calendar.AddDays(this.DateTime, days));
}
public double DiffDays(UmAlQuraDate other)
{
TimeSpan diff = DateTime.Subtract(other.DateTime);
return diff.Days;
}
}
- From the Build menu, select Deploy. This registers the assembly and creates the type in the SQL Server database.
For more information about how to register the User-Defined Types in SQL Server please check this article, http://msdn.microsoft.com/en-us/library/ms131079.aspx
Second step,Use the UmAlQuraDate to do conversion or declare types in your database tables.
To use the CLR data type in SQL server Management Studio , you first need to enable CLR, or you will receive the following error message: “Execution of user code in the .NET Framework is disabled. Enable ”clr enabled’ configuration option.” To fix this, run
exec sp_configure 'clr enabled', 1
then:
RECONFIGURE
You can now use the CLR data type.
This is an example that accepts UmAlQura dates and displays them:
DECLARE @MyDate UmAlQuraDate
SET @MyDate = UmAlQuraDate::ParseArabic('01/02/1430')
PRINT @MyDate.ToStringUsingFormat('F')
Output:
01/صفر/1430 12:00:00 ص
To convert from Gregorian date to Um Al Qura date, check this example:
DECLARE @gregd DateTime
DECLARE @MyDate UmAlQuraDate
SET @gregd = 'February 20, 2009'
SET @MyDate = UmAlQuraDate::FromSqlDateTime(@gregd)
PRINT N'Gregorean Date: ' + CAST(@gregd AS nvarchar(30));
PRINT N'Um AlQura Date (short format):' + @MyDate.ToString();
PRINT N'Um AlQura Date (long format):' + @MyDate.ToStringUsingFormat('F')
This is the output:
Gregorean Date: Feb 20 2009 12:00AM
Um AlQura Date (short format):25/02/30 12:00:00 ص
Um AlQura Date (long format):25/صفر/1430 12:00:00 ص
To convert from Um Al Qura date to Gregorian, check this example:
DECLARE @MyDate UmAlQuraDate
SET @MyDate = UmAlQuraDate::ParseArabic('01/09/1430')
PRINT N'Gregorean Date: ' + CAST(@MyDate.ToSqlDateTime() AS nvarchar(30));
PRINT N'Um AlQura Date (short format):' + @MyDate.ToString();
PRINT N'Um AlQura Date (long format):' + @MyDate.ToStringUsingFormat('F')
Output is:
Gregorean Date: Aug 21 2009 12:00AM
Um AlQura Date (short format):01/09/30 12:00:00 ص
Um AlQura Date (long format):01/رمضان/1430 12:00:00 ص
In addition to the above, you can also create a UmAlQuraDate field
Create the Table:
CREATE TABLE DateTable (
GregDate DateTime,
UmAlQura UmAlQuraDate
)
Convert Western Dates to UmAlQura dates in the table:
update DateTable
set UmAlQura = UmAlQuraDate::FromSqlDateTime(GregDate)
Retrieve the value of the UmAlQura dates in the table, you need to type cast to String:
SELECT UmAlQura.ToString()
FROM DateTable
I hope you find this useful
-
I had an interesting customer scenario, which is common among developers that deal with more than language. Basically you have an English WinForm application that uses the DataGridView , but you have the Names field in Arabic. So, you want to keep the DataGridView in English , but change one column only to right-to-left.
I have the following easy steps to accomplish this. First you need to define two things:
You’ll use the Unicode RightToLeft Embedding character to help you display the tooltips properly.
private char rle_char = (char)0x202B;// RLE embedding Unicode control character
To make things simple, I’ll define the Column ID that needs to be RTL.
private int RTLColumnID = 1; // This sample assumes that Column "1" will be RTL
First, handle the DataGridView.CellPainting event and add the following code, which simply draws the cell and align it to the right and rtl flags.
private void RTLColumnsDGV_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.ColumnIndex == RTLColumnID && e.RowIndex >= 0)
{
e.PaintBackground(e.CellBounds, true);
TextRenderer.DrawText(e.Graphics, e.FormattedValue.ToString(),
e.CellStyle.Font, e.CellBounds, e.CellStyle.ForeColor,
TextFormatFlags.RightToLeft | TextFormatFlags.Right);
e.Handled = true;
}
}
Second, handle the DataGridView.EditingControlShowing event. You need to set RightToLeft=Yes to this edit control.
private void RTLColumnsDGV_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
if (e.Control != null)
{
DataGridView DGridView = sender as DataGridView;
if (DGridView.CurrentCell.ColumnIndex == RTLColumnID)
e.Control.RightToLeft = RightToLeft.Yes;
}
}
Third, handle the DataGridView.CellToolTipTextNeeded event. You need to add the RLE Unicode control character to make sure the
private void RTLColumnsDGV_CellToolTipTextNeeded(object sender, DataGridViewCellToolTipTextNeededEventArgs e)
{
if (e.ColumnIndex == RTLColumnID && e.RowIndex >= 0)
if (e.ToolTipText != String.Empty)
e.ToolTipText = rle_char + e.ToolTipText;
}
I recommend that you don’t set the cell alignment for these columns, leave it as “notset” so that it isn’t confusing.
The above steps will fix the cells but what about the title? Well, in the Form.Load you can set the title to Right align and add the RLE_Char to the beginning to display it properly. Thisis the code for your reference:
DGridView.Columns[RTLColumnID].HeaderText = rtlchar+DGridView.Columns[RTLColumnID].HeaderText;
if (DGridView.Columns[RTLColumnID].HeaderCell.ToolTipText != String.Empty)
DGridView.Columns[RTLColumnID].HeaderCell.ToolTipText = rtlchar + DGridView.Columns[RTLColumnID].HeaderCell.ToolTipText;
DGridView.Columns[RTLColumnID].HeaderCell.Style.Alignment = DataGridViewContentAlignment.TopRight;
The same rational applies if you have more than one column too. I hope this helps :)
-
In short, there is no Arabic Support in Silverlight 2, however there are some workarounds. There is a specific solution from Santeon check the website, http://www.santeon.com/silverlight . You might also check out CodePlex , there are a couple of solutions, http://www.codeplex.com/SilverlightRTL and http://www.codeplex.com/SilverRTL. I downloaded and tried the first solution. It’s interesting but not bug free. There are two main tasks to add RTL support in text:
1) Need to divide your string into rtl and ltr runs and then re-order each. In addition to right-align text.
2) In the case of Arabic, you also need to do the shaping of characters, since the character shapes are different depending on where the character is in the word. There could be upto 4 shapes in a character, beginning form, middle form, ending form and isolated form
These are the two main tasks, of course there is additional logic of getting the text and putting it back.
This is a good attempt to add RTL support; however, there are unexpected behavior, check the issues at CodePlex.
-
In my earlier post, I mentioned the different consideration when dealing with rtl (or Bidi) text. This time I’m going to post the sample with more in-depth discussion.
1) I created a WPF Windows application: RTLApplication.
2) Created a CustomControl and called it RTL Control. This is the rendering code, and the highlight shows the differences to insure that RTL rendering is correct:
protected override void OnRender(DrawingContext drawingContext)
{
// Draw a rectangle at the beginning
Rect rect = new Rect(new Point(5, 5), new Size(25, 25));
drawingContext.DrawRectangle(Brushes.Brown, (Pen)null, rect);
// Prepare to draw the text
String Text = "أهلاً Hello و مرحباً بكم.";
Geometry textGeometry;
Point origin = new Point();
origin.Y = 0;
int x_margin = 40;
origin.X = x_margin;
// Create the formatted text based on the properties set.
FormattedText formattedText = new FormattedText(
Text,CultureInfo.CurrentUICulture,
FlowDirection,
new Typeface("Arial"), 36, Brushes.Black);
//Use a gradient to display red- green- and blue
GradientStopCollection gsc = new GradientStopCollection();
gsc.Add(new GradientStop(Colors.Red, 0));
gsc.Add(new GradientStop(Colors.Green, 0.5));
gsc.Add(new GradientStop(Colors.Blue, 1));
// Build the geometry object that represents the text.
if (FlowDirection == FlowDirection.RightToLeft)
{
double m11 = -1;
double m22 = 1;
double offsetX = formattedText.Width;
double offsetY = 0;
drawingContext.PushTransform(
new MatrixTransform(m11, 0, 0, m22, offsetX, offsetY));
origin.X = formattedText.Width - x_margin;
}
textGeometry = formattedText.BuildGeometry(origin);
drawingContext.DrawGeometry(new LinearGradientBrush(gsc),
new System.Windows.Media.Pen(Brushes.Blue, 0),
textGeometry);
if (FlowDirection == FlowDirection.RightToLeft)
drawingContext.Pop();
// Draw a circle at the end
drawingContext.DrawEllipse(Brushes.DeepSkyBlue, (Pen)null,
new Point(formattedText.Width + x_margin + 10, 17), 12, 12);
}
3) Then I’ll go back to my MainWindow. I’ll add reference to my application to access my control:
xmlns:MyNamespace="clr-namespace:RTLApplication"
4) Add a button to switch the FlowDirection:
if (FlowDirection == FlowDirection.RightToLeft)
FlowDirection = FlowDirection.LeftToRight;
else
FlowDirection = FlowDirection.RightToLeft;
5) Finally run the application.
This is a complete application, enjoy!
-

November was a very hectic month. I participated as a speaker in the IT Evolution event, touring 6 cities in Gulf. IT Evolution 08 is a one-day event. There are separate tracks for IT professionals and developers. The event was organized by the DPE team in Gulf to tour 6 cities, Abu Dhabi (UAE), Manama (Bahrain), Muscat (Oman), Doha (Qatar), Dubai(UAE) and Kuwait. I gave a session about Visual Studio 2008 SP1 Enhancements, including info on new SQL 2008 support, WPF, ADO.NET Entity Framework, and Data Services (Astoria)… etc in addition to the new Arabic CLIP for VS 2008.
For more info about the event, please visit its website.
After that I gave a session specifically promoting Arabic CLIP to a group of teachers in an event in Kuwait.
Now, almost most of the people are out of office (OOF) and I have some time for my blog… by the way, I met people who followed my blog on the road… and it gave me more motivation to write more blogs and add more samples… so stay tuned, for more samples.
-
Microsoft CLIP (or Microsoft Captions Language Interface Pack) is a language solution that uses tooltips or a window to display translation. CLIP works with any application to show translations in the Tooltip and/or the CLIP Window. You can also add/edit/delete your own translations
Now for the first-time we are announcing Arabic CLIP. It’s a community driven effort, with the help of university in Saudi Arabia. More than 13,000+ terms\ 40,000 words translated to Arabic – based on the terms from the Express editions of Visual Studio 2008
Available at:
http://www.microsoft.com/downloads/details.aspx?FamilyID=4e5258d2-52f4-46b8-8b74-da2dbec7c2f7&displaylang=ar
-
Drawing Text using FormattedText
FormattedText Class offers low-level method to manage drawing text in Windows Presentation Foundation (WPF). It processes text as graphical elements, instead of text in controls such as the TextBox and TextBlock, which implement the FlowDirection model or the XPS document model.
Basically, you should avoid using Formatted text and use the textblock, whenever possible. TextBlock honors the FlowDirection property and render the text properly. However, sometimes you need to do your own rendering of text. In this case you need to take care of the rendering of RightToLeft text.
This is the declaration of the FormattedText:
public FormattedText(
string textToFormat,
CultureInfo culture,
FlowDirection flowDirection,
Typeface typeface,
double emSize,
Brush foreground,
NumberSubstitution numberSubstitution
)
I’m not going to discuss all the parameters of the FormattedText, let’s examine the RTL related paramaters:
Parameters
culture
Type: System.Globalization..::.CultureInfo
The specific culture of the text. It’s important set the culture to the valid entry , whether its’ the UICulture or you might default to non-RTL culture, if you need to opy-out of RTL behavior.
flowDirection
Type: System.Windows..::.FlowDirection
The direction the text is read. In the case of RTL text we need to set the value appropriately, because this influences how text is displayed. If we set it to FlowDirection=LeftToRight then the fullstop and the trailing neutral characters would be on the left of the text, and other wise it would be on the right of text. So Avoid setting it by default to FlowDirection=LeftToRight – and use the shell property “LayoutIsRightToLeft”to display the text appropriately.
For example as this sample:
System.Windows.FlowDirection flow_direction;
if (LayoutIsRightToLeft == true)
flow_direction = FlowDirection.RightToLeft;
else
flow_direction = FlowDirection.LeftToRight;
numberSubstitution
Type: System.Windows.Media..::.NumberSubstitution
The number substitution behavior to apply to the text. Some RTL cultures use different digit shapes from those we are familiar with in the West. The below table illustrates some numbering systems used by diverse cultures.
Digits are used in calculations; therefore, it’s not practical to provide alternate Unicode code characters for each set of digit shapes. It’s the task of the OS and applications to render numbers correctly. The NumberSubstitution class provides functionality that allows different cultures to substitute the appropriate digit shapes at rendering time. This functionality is similar to the one used for providing font substitution and language dependent font rendering.
These are a list of possible NumberSubstitutionMethod
|
Member name |
Description |
|
AsCulture |
Default. Specifies that the substitution method should be determined based on the number culture's DigitSubstitution property value. |
|
Context |
If the number culture is an Arabic or Farsi culture, specifies that the digits depend on the context. Either traditional or Latin digits are used depending on the nearest preceding strong character, or, if there is none, the text direction of the paragraph. |
|
European |
Specifies that code points 0x30-0x39 are always rendered as European digits, in which case, no number substitution is performed. |
|
NativeNational |
Specifies that numbers are rendered using the national digits for the number culture, as specified by the culture's NativeDigits property value. |
|
Traditional |
Specifies that numbers are rendered using the traditional digits for the number culture. For most cultures, this is the same as the DigitShapes..::.NativeNational enumeration value. However, using NativeNational can result in Latin digits for some Arabic cultures, whereas using Traditional results in Arabic digits for all Arabic cultures. |
In most cases the default value is sufficient, however, you may need to display the digits as Western only and not as per the culture.
You will need more work. The “FormattedText” needs to be RightToLeft. This would display the mixed English and Arabic text properly and the full-stop would be displayed on the left side of text. Therefore you need to set the formattedText, FlowDirection to RightToLeft:
flow_direction = FlowDirection.LeftToRight;
with this code:
if (FlowDirection == FlowDirection.RightToLeft)
{
flow_direction = FlowDirection.RightToLeft;
}
else
{
flow_direction = FlowDirection.LeftToRight;
}
The text is displayed to the left of the display area, instead of the right of the display area. Therefore you should adjust the display origin to adjust the text display. You need to set the origin.X to a new origin and the transformation offset, for our case where FlowDirection.RightToLeft text. Another important effect of setting the FlowDirection parameter to RightToLeft is that the text is formatted to the left of the “origin”, instead of the right. The text is actually mirrored and not readable. So you need to apply a reflection transformation.
if (FlowDirection == FlowDirection.RightToLeft)
{
double m11 = -1;
double m22 = 1;
double offsetX = formattedText.Width;
double offsetY = 0;
drawingContext.PushTransform(
new MatrixTransform(m11, 0, 0, m22, offsetX, offsetY));
origin.X = formattedText.Width - x_margin;
}
Don’t forget to remove the transformation, when you finish drawing text.
if (FlowDirection == FlowDirection.RightToLeft)
drawingContext.Pop();
I hope this was useful.