Thursday, January 28, 2010

Changing the text selection color in WPF

Short answer: you can't! The color of the text selection (not of the background) is given by an (internal) class System.Windows.Document.CaretElement, inheriting from Adorner. Here is the bit of crappy code that makes this impossible:

protected override void OnRender(DrawingContext drawingContext)
if (this._selectionGeometry != null)
Brush brush = new SolidColorBrush(SystemColors.HighlightColor);
brush.Opacity = 0.4;
Pen pen = null;
drawingContext.DrawGeometry(brush, pen, this._selectionGeometry);

And you might be thinking that it is a simple template change issue and if you don't add the bloody caret to the template it will work. Wrong! The Caret element is instantiated via code in classes as TextSelection, as an implementation of the ITextSelection interface which only has a getter for the Caret property. The TextSelection class is instantiated in all the controls that support text selection as internal properties or fields. Yay!

So unless you recreate the entire selection functionality, you are stuck with the SystemColors.HighlightColor color for selection. As Dr. WPF himself says: "It is entirely impossible in the current .NET releases (3.0 & 3.5 beta). The control is hardcoded to use the system setting... it doesn't look at the control template at all."

Better luck in WPF 4.0... maybe.