The trick would be to get what ever panel (I guess its a Canvas?) that you are overlaying the RichTextBox with to actually exist within the same ScrollViewer
that rich text exists in.
The following is very rough idea but should get you on the path to reasonable solution.
You can do this using a custom style for the RichTextBox
. The default style for this control can be found here.
Copy this style into a resource in your containing UserControl and point your RichTextBox
Style
property at it. So far nothing is different but now you can play about with the template. The relevant portion currently looks like this:-
<Border x:Name="MouseOverBorder" BorderThickness="1" BorderBrush="Transparent">
<ScrollViewer x:Name="ContentElement" Padding="{TemplateBinding Padding}" BorderThickness="0" IsTabStop="False" />
</Border>
Now we can tweak it like this:-
<Border x:Name="MouseOverBorder" BorderThickness="1" BorderBrush="Transparent">
<ScrollViewer Padding="{TemplateBinding Padding}" BorderThickness="0" IsTabStop="False">
<Grid>
<ContentControl x:Name="ContentElement" />
<Canvas x:Name="HighlightOverlay" />
</Grid>
</ScrollViewer>
</Border>
You'll note that we've moved the name "ContentElement" from the ScrollViewer
to the new ContentControl
. Having a FrameworkElement
called "ContentElement" is the only feature that the RichTextBox stipulates about its template.
Now overlaying this ContentControl
we can place a Canvas
where you can place your highlighting rectangles. If the user scrolls this RichTextBox
the whole Grid
containing both the Content and the Highlights will scroll together.
The only remaining trick is acquiring the "HighlightOverlay" so that you can add your rectangle to it. Here is some code that will grab it:-
private Canvas HightlightOverlay;
public MyUserControl()
{
InitializeComponent();
MyRichText.LayoutUpdated += MyRichText_LayoutUpdated;
}
void MyRichText_LayoutUpdated(object sender, EventArgs e)
{
HightlightOverlay = MyRichText.Descendents()
.OfType<Canvas>()
.FirstOrDefault(elem => elem.Name == "HighlightOverlay");
}
You will be wondering where the Descendents
method is coming from, it is here.