I've recently been developing an RTF Editor which is only a simple UserControl
that has a RichTextBox
with a couple Events like PreviewTextInput
and PreviewMouseUp
.
I noticed something slightly annoying though.
The Performance of the RichTextBox
is absolutely terrible whenever the UI is being resized and the RichTextBox
has a lot of Text to cause its Wrapping Algorithm to fire.
This gives the Application a really sloppy feel, as if it is poorly optimized (even though it isn't).
At first I noticed this performance hit while selecting Text, so instead of using the SelectionChanged
event, I decided to use the PreviewMouseUp
event and then fetch the Selection.
Then after further testing I found out that the resize also caused huge loads. And I'm talking about loads ranging between 5% -> 30% with a Quad-Core CPU running at 3.8GHz!
To further test it out, I decided to comment out my RichTextBox
and only include a new RichTextBox
with no defined Property
<RichTextBox/>
Inserting this into a Window, filling with Text, and then resizing the Window to cause the Wrapping Algorithm did the same again, up to 30% usage!
I tried to research about this matter, and most people ended up recommending setting the PageWidth
to high values in order to prevent Wrapping:
richTextBox1.HorizontalScrollBarVisibility = ScrollBarVisibility.Visible;
richTextBox1.Document.PageWidth = 1000;
Which I do not want, since the previous Version of the Editor I wrote was made with WinForms and could do Wrapping effortlessly, and I also want it in the new WPF Version.
Did anyone else ever face this issue? If yes, could you please point me into the right direction to remove this huge strain on the hardware?
I'm a bit sad because I love WPF, but I did find one or the other Object that is really unoptimized and/or not practical in comparison to the WinForms counterpart, the RichTextBox
seems to be another one of those cases :(
Sorry for the huge amount of Text, but I really wanted to Document this neatly in case some other poor soul faces this issue and for you guys to see what I've tried so far.
One way to overcome this issue might be to switch to "no wrap" mode when window is being resized, but when user finished with resizing - switch back to normal mode. Then wrapping algorithm will be executed just once at the end and users should still have smooth feeling about your application. Sample code:
public partial class MainWindow : Window
{
public MainWindow() {
InitializeComponent();
this.SizeChanged += OnSizeChanged;
}
private Timer _timer;
private void OnSizeChanged(object sender, SizeChangedEventArgs e) {
// user started resizing - set large page width
textBox.Document.PageWidth = 1000;
// if we already setup timer - stop it and start all over
if (_timer != null) {
_timer.Dispose();
_timer = null;
}
_timer = new Timer(_ => {
// this code will run 100ms after user _stopped_ resizing
Dispatcher.Invoke(() =>
{
// reset page width back to allow wrapping algorithm to execute
textBox.Document.PageWidth = double.NaN;
});
}, null, 100, Timeout.Infinite);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With