In This Topic
The Syntax Coloring section described how you can use C1TextRange objects to modify the style of parts of a document without moving the selection. In some cases, however, you may want to modify only the view, and not the document itself.
For example, the current selection is highlighted with different foreground and background colors. This style change does not belong to the document itself; it belongs to the view. Other examples are syntax coloring and as-you-type spell-checking.
The C1RichTextBox control supports these scenarios with the StyleOverrides property. This property contains a collection of objects that specify ranges and style modifications to be applied to the view only. This approach has two advantages over applying style modifications to C1TextRange objects as you did in the previous section:
- The style overrides are not applied to the document, and therefore are not applied when you save a document as HTML (you would not normally want the current selection and spelling error indicators to be persisted to a file).
- Because the changes are not added to the document, and only affect the part that is currently visible, this approach is much more efficient than changing C1TextRange objects directly.
The limitation of this approach is that the style changes cannot involve style elements that affect the document flow. You can use style overrides to change the background, foreground, and to underline parts of the document. But you cannot change the font size or style, for example, since that would affect the document flow.
In the following section learn how to implement Overriding Styles in RichTextBox .NET and .NET Framework versions.
Let us demonstrate the use of style overrides by modifying the previous syntax coloring example.
First, we need to declare a C1RangeStyleCollection object and add that to the control's StyleOverrides collection. Once that is done, any overrides added to our collection will be applied to the control. We will later populate the collection with the syntax-colored parts of the document.
Visual Basic |
Copy Code
|
Private _rangeStyles As New C1RangeStyleCollection()
Public Sub New()
InitializeComponent()
_rtb = New C1RichTextBox()
LayoutRoot.Children.Add(_rtb)
AddHandler _rtb.TextChanged, AddressOf tb_TextChanged
_rtb.FontFamily = New FontFamily("Courier New")
_rtb.FontSize = 16
_rtb.Text = GetStringResource("w3c.htm")
' Add our C1RangeStyleCollection to the control's
' StyleOverrides collection
_rtb.StyleOverrides.Add(_rangeStyles)
End Sub
|
C# |
Copy Code
|
C1RangeStyleCollection _rangeStyles = new C1RangeStyleCollection();
public MainPage()
{
InitializeComponent();
_rtb = new C1RichTextBox();
LayoutRoot.Children.Add(_rtb);
_rtb.TextChanged += tb_TextChanged;
_rtb.FontFamily = new FontFamily("Courier New");
_rtb.FontSize = 16;
_rtb.Text = GetStringResource("w3c.htm");
// Add our C1RangeStyleCollection to the control's
// StyleOverrides collection
_rtb.StyleOverrides.Add(_rangeStyles);
}
|
Now, all we need to do is modify the UpdateSyntaxColoring method shown earlier and have it populate our collection of range styles (instead of applying the coloring to the document as we did before):
Visual Basic |
Copy Code
|
' Perform syntax coloring using StyleOverrides collection
' (takes a fraction of a second to highlight the default document)
Private Sub UpdateSyntaxColoring(ByVal rtb As C1RichTextBox)
' Initialize regular expression used to parse HTML
String pattern =
"</?(?<tagName>[a-zA-Z0-9_:\-]+)" +
"(\s+(?<attName>[a-zA-Z0-9_:\-]+)" +
(?<attValue>(\s*=\s*""(^"")+"")?))*\s*/?>"
' Initialize styles used to color the document
Dim key As var = C1TextElement.ForegroundProperty
Dim brDarkBlue As var = New C1TextElementStyle()
brDarkBlue(key) = New SolidColorBrush(Color.FromArgb(255, 0, 0, 180))
Dim brDarkRed As var = New C1TextElementStyle()
brDarkRed(key) = New SolidColorBrush(Color.FromArgb(255, 180, 0, 0))
Dim brLightRed As var = New C1TextElementStyle()
brLightRed(key) = New SolidColorBrush(Colors.Red)
' Remove old coloring
_rangeStyles.Clear()
' Highlight the matches
Dim input As var = rtb.Text
Dim m As Match
For Each m In Regex.Matches(input,pattern)
' Select whole tag, make it dark blue
Dim range As var = rtb.GetTextRange(m.Index,m.Length)
_rangeStyles.Add(New C1RangeStyle(range,brDarkBlue))
' Select tag name, make it dark red
Dim tagName As var = m.Groups("tagName")
range = rtb.GetTextRange(tagName.Index, tagName.Length)
_rangeStyles.Add(New C1RangeStyle(range,brDarkRed))
' Select attribute names, make them light red
Dim attGroup As var = m.Groups("attName")
If Not attGroup Is Nothing Then
Dim att As Capture
For Each att In attGroup.Captures
range = rtb.GetTextRange(att.Index, att.Length)
_rangeStyles.Add(New C1RangeStyle(range,brLightRed))
Next
End If
Next
End Sub
|
C# |
Copy Code
|
// Perform syntax coloring using StyleOverrides collection
// (takes a fraction of a second to highlight the default document)
void UpdateSyntaxColoring(C1RichTextBox rtb)
{
// Initialize regular expression used to parse HTML
string pattern =
@"</?(?<tagName>[a-zA-Z0-9_:\-]+)" +
@"(\s+(?<attName>[a-zA-Z0-9_:\-]+)" +
(?<attValue>(\s*=\s*""[^""]+"")?))*\s*/?>";
// Initialize styles used to color the document
var key = C1TextElement.ForegroundProperty;
var brDarkBlue = new C1TextElementStyle();
brDarkBlue[key] = new SolidColorBrush(Color.FromArgb(255, 0, 0, 180));
var brDarkRed = new C1TextElementStyle();
brDarkRed[key] = new SolidColorBrush(Color.FromArgb(255, 180, 0, 0));
var brLightRed = new C1TextElementStyle();
brLightRed[key] = new SolidColorBrush(Colors.Red);
// Remove old coloring
_rangeStyles.Clear();
// Highlight the matches
var input = rtb.Text;
foreach (Match m in Regex.Matches(input, pattern))
{
// Select whole tag, make it dark blue
var range = rtb.GetTextRange(m.Index, m.Length);
_rangeStyles.Add(new C1RangeStyle(range, brDarkBlue));
// Select tag name, make it dark red
var tagName = m.Groups["tagName"];
range = rtb.GetTextRange(tagName.Index, tagName.Length);
_rangeStyles.Add(new C1RangeStyle(range, brDarkRed));
// Select attribute names, make them light red
var attGroup = m.Groups["attName"];
if (attGroup != null)
{
foreach (Capture att in attGroup.Captures)
{
range = rtb.GetTextRange(att.Index, att.Length);
_rangeStyles.Add(new C1RangeStyle(range, brLightRed));
}
}
}
}
|
The revised code is very similar to the original. Instead of creating brushes to color the document, it creates C1TextElementStyle objects that contain an override for the foreground property. The code starts by clearing the override collection, then uses a regular expression to locate each HTML tag in the document, and finally populates the overrides collection with C1RangeStyle objects that associate ranges with C1TextElementStyle objects.
If you run this new version of the code, you should notice the dramatic performance increase. The new version is thousands of times faster than the original.
Let us demonstrate the use of style overrides by modifying the previous syntax coloring example.
First, we need to declare a C1RangeStyleCollection object and add that to the control's StyleOverrides collection. Once that is done, any overrides added to our collection will be applied to the control. We will later populate the collection with the syntax-colored parts of the document.
C# |
Copy Code
|
C1RangeStyleCollection _rangeStyles = new C1RangeStyleCollection();
public OverridingStyles()
{
InitializeComponent();
richTextbox.TextChanged += RichTextboxTextChanged;
richTextbox.FontFamily = new FontFamily("Courier New");
richTextbox.FontSize = 16;
richTextbox.Text = "<html>\r\t<body>\r\t\t<p height=\"20\">This is sample html syntax colored by overriding style.</p>\r\t</body>\r</html>";
// Add our C1RangeStyleCollection to the control's
// StyleOverrides collection
richTextbox.StyleOverrides.Add(_rangeStyles);
|
Now, all we need to do is modify the UpdateSyntaxColoring method shown earlier and have it populate our collection of range styles (instead of applying the coloring to the document as we did before):
C# |
Copy Code
|
// Perform syntax coloring using StyleOverrides collection
// (takes a fraction of a second to highlight the default document)
void UpdateSyntaxColoring(C1RichTextBox rtb)
{
// Initialize regular expression used to parse HTML
string pattern =
@"</?(?<tagName>[a-zA-Z0-9_:\-]+)" +
@"(\s+(?<attName>[a-zA-Z0-9_:\-]+)(?<attValue>(=""[^""]+"")?))*\s*/?>";
// Initialize styles used to color the document
var key = C1TextElement.ForegroundProperty;
var brDarkBlue = new C1TextElementStyle();
brDarkBlue[key] = new SolidColorBrush(Color.FromArgb(255, 0, 0, 180));
var brDarkRed = new C1TextElementStyle();
brDarkRed[key] = new SolidColorBrush(Color.FromArgb(255, 180, 0, 0));
var brLightRed = new C1TextElementStyle();
brLightRed[key] = new SolidColorBrush(Colors.Red);
// Remove old coloring
_rangeStyles.Clear();
// Highlight the matches
var input = rtb.Text;
foreach (Match m in Regex.Matches(input, pattern))
{
// Select whole tag, make it dark blue
var range = rtb.GetTextRange(m.Index, m.Length);
_rangeStyles.Add(new C1RangeStyle(range, brDarkBlue));
// Select tag name, make it dark red
var tagName = m.Groups["tagName"];
range = rtb.GetTextRange(tagName.Index, tagName.Length);
_rangeStyles.Add(new C1RangeStyle(range, brDarkRed));
// Select attribute names, make them light red
var attGroup = m.Groups["attName"];
if (attGroup != null)
{
foreach (Capture att in attGroup.Captures)
{
range = rtb.GetTextRange(att.Index, att.Length);
_rangeStyles.Add(new C1RangeStyle(range, brLightRed));
}
}
}
|
The revised code is very similar to the original. Instead of creating brushes to color the document, it creates C1TextElementStyle objects that contain an override for the foreground property. The code starts by clearing the override collection, then uses a regular expression to locate each HTML tag in the document, and finally populates the overrides collection with C1RangeStyle objects that associate ranges with C1TextElementStyle objects.
If you run this new version of the code, you should notice the dramatic performance increase. The new version is thousands of times faster than the original.