I want to remove all hyperlinks located in a RichTextBox but not the runs inside the hyperlinks.
My plan is for each hyperlink:
- gather all runs inside it
- remove the hyperlink
- re-insert the runs
While extracting the runs I face this problem: If the hyperlink consists of one unformatted run, I don't get the run but also the surrounding hyperlink.
Please try this code:
Xaml:
<RichTextBox Name="rtb" Grid.Column="0" Grid.Row="0" IsDocumentEnabled="True">
<FlowDocument>
<Paragraph>
<Hyperlink>
<Run>HyperlinkUnformatted</Run>
</Hyperlink>
</Paragraph>
<Paragraph>
<Hyperlink>
<Run>Hyper</Run><Run Background="Yellow">link</Run><Run>Formatted</Run>
</Hyperlink>
</Paragraph>
</FlowDocument>
</RichTextBox>
C#:
// All runs inside the RichTextBox
List<Run> runs = runsGet(rtb.Document.ContentStart, rtb.Document.ContentEnd);
foreach (Run run in runs)
{
TextRange rangeOfRun = new TextRange(run.ContentStart, run.ContentEnd);
string runAsString = rangeToString(rangeOfRun, DataFormats.Xaml);
MessageBox.Show(runAsString);
}
/// <summary>
/// Returns all runs between startPos and endPos.
/// </summary>
private List<Run> runsGet(TextPointer startPos, TextPointer endPos)
{
List<Run> foundRuns = null;
TextPointer currentPos = startPos;
while (currentPos != null && currentPos.CompareTo(endPos) <= 0)
{
Run nextRun = runNextGet(currentPos);
if (nextRun == null) break;
if (nextRun.ContentStart.CompareTo(endPos) <= 0)
{
if (foundRuns == null) foundRuns = new List<Run>();
foundRuns.Add(nextRun);
currentPos = nextRun.ContentEnd.GetNextInsertionPosition(LogicalDirection.Forward);
}
else
{
break;
}
}
return foundRuns;
}
/// <summary>
/// Returns first run located at startPos or behind.
/// </summary>
private Run runNextGet(TextPointer startPos)
{
TextPointer currentPos = startPos;
while (currentPos != null)
{
if (currentPos.Parent is Run)
{
return currentPos.Parent as Run;
}
else
{
currentPos = currentPos.GetNextInsertionPosition(LogicalDirection.Forward);
}
}
return null;
}
/// <summary>
/// Returns a text area as Xaml string (if dataFormat is DataFormats.Xaml).
/// </summary>
private string rangeToString(TextRange range, string dataFormat)
{
using (MemoryStream memStream = new MemoryStream())
{
using (StreamWriter streamWriter = new StreamWriter(memStream))
{
range.Save(memStream, dataFormat);
memStream.Flush();
memStream.Position = 0;
StreamReader streamReader = new StreamReader(memStream);
return streamReader.ReadToEnd();
}
}
}