EDIT: You can find an update to this post here: Code editor control with syntax highlighting for Silverlight available.
This is a demo about leveraging the databinding and templating support in Silverlight and the MVVM pattern to create a simple syntax highlighting textbox control.
The idea is to have an invisible TextBox (handling the editing) overlapping a ItemsControl that uses TextBlocks to highlight the keywords in the text. The ItemsSource property of the ItemsControl is bound to a collection property on the ViewModel, so we only need to update this collection in order to maintain the controls in sync.
In the end we’ll get something like this:

We start by creating a new Silverlight Application project and adding a CodeEditorView and a CodeEditorViewModel.

Add the basic INotifyPropertyChanged implementation to the ViewModel.
We’ll use two entity classes for storing the lines and words of code: CodeWord and CodeLine.
Add CodeText and CodeLines properties to the ViewModel. The CodeText property will be bound to the Text property of the overlapping TextBox. Any change to its value will cause the CodeLines collection to be updated, resulting in turn in the update of the underlying TextBlocks.
We’ll add a AddCodeWord() method to CodeLine to handle the appending of text to that line and decide whether we’re dealing with a keyword or not. We’ll try to reuse existing CodeWords if possible, in order to keep the resulting TextBlocks number low. AddCodeWord also updates a Text property that we can use to decide if two lines are equal.
We can now write an UpdateCodeWords method that updates the CodeLines when the CodeText property changes. It basically determines the lines that changed and rebuilds the corresponding CodeLines. Of course, this can be replaced with a real parsing module.
In order to display the colors depending on the CodeWordType, we need to add a converter.
For designing, you can use Expression Blend, the new designer in VS .NET 2010, or you can just type the XAML by hand. We’ll use Blend for this demo.
We star by adding a ItemsControl and a TextBox to the UserControl.

We’ll set the Background brush for the TextBox to None (or transparent) and the Foreground to 30% opacity, so we can validate the design – we’ll set it to 0% in the end.
Note: setting the Foreground to None causes the SelectionForeground to disappear too, for some reason – we need the Selection to keep working as usual, for editing.

In order to have a nice design experience, we’ll create a DesignData file for the CodeEditorViewModel. Add a plain text file to the project and then change its BuildAction to DesignData.

Set the design DataContext for the LayoutRoot of the UserControl:
d:DataContext=”{d:DesignData Source=/DesignData/DD_CodeEditorVM.xaml}”
Then set the DataBinding for the Text property of the TextBox. Notice the “Update source when” is set to Explicit.

Normally, the TextBox updates the backing property on FocusLost. We need to update it on every change:
We’ll bind the ItemsSource of the ItemsControl to the CodeLines property.

We can now see that the controls use our design data.

To display meaningful text instead of the class name, we need to define the ItemTemplate and the ItemsPanelTemplate for the ItemsControl.

The ItemTemplate for the CodeLine will contain only another ItemsControl, with its ItemsSource property databound to the CodeWords property of the CodeLine.


In turn, we’ll edit the ItemTemplate for this ItemsControl and set it to be a TextBlock, with its Text property bound to the Text property of the CodeWord.

We’ll use the default ItemPanelTemplate, consisting of a StackPanel – we’ll just set its Orientation to be Horizontal for the CodeWordsPanelTemplate and Vertical for the CodeLinesPanelTemplate.
We now have this overlapping:

We can set the Foreground binding for the inner TextBlocks, using the CodeWordTypeToBrushConverter.

And get this overlapping:

If we set the Up and Left margins of the ItemsControl to 4, we get this:

As you can see, it almost perfect, but looses accuracy to the right and down. To fix this, we need to disable UseLayoutRounding for the ItemsControl.

And the result – perfect overlap:

The problem we still have is scrolling – the text in the textbox is not synched with the text in the ItemsControl when scrolling.
To fix this, we’ll group the two controls into a Grid and then into a ScrollViewer.

We need to set the HorizontalScrollBarVisibility and VerticalScrollBarVisibility to Disabled for the TextBox and to Auto for the ScrollViewer.
And that’s it – see it in action:

You can download the source code for the demo here:
SyntaxHighlightingDemo.zip (25.19 kb)
Or, see a control that’s based on this at work in CoderProof – online developer interview tool.
nice!
i like this
I have a trouble using this control, how can i set a default code to be loaded? there’s no propert to set or get the code in the control.
Try the newer version, found here: http://www.vladhorby.com/wpblog/2011/01/24/code-editor-control-with-syntax-highlighting-for-silverlight-available