我想删除位于RichTextBox中的所有超链接,但不删除超链接内的运行。
我的计划是针对每个超链接:
在提取运行时,我遇到了这个问题: 如果超链接包含一个未格式化的运行, 我没有得到跑步,但也没有得到周围的超链接。
请尝试以下代码:
的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();
}
}
}
答案 0 :(得分:0)
您要做的是,对于每个超链接,将超链接的Inlines复制到单独的XamlPackage
,然后将它们粘贴回FlowDocument,覆盖Hyperlink
本身。不幸的是,由于TextRange.Save()
“有用”expands the selected range到nearest text insertion boundaries,因此天真的实施方式会失败。由于超链接与其第一个内联的开头(大小为零)之间的空间不是有效的插入符号位置,因此不是有效的插入位置,因此文本范围将扩展为包括超链接。它由此包含在包中,并在粘贴时重新创建。
要解决此问题,您可以在现有内联之前和之后插入一些其他虚拟文本:
public static class FlowDocumentHelper
{
public static IEnumerable<DependencyObject> WalkTreeDown(this DependencyObject root)
{
if (root == null)
throw new ArgumentNullException();
yield return root;
foreach (var child in LogicalTreeHelper.GetChildren(root).OfType<DependencyObject>())
foreach (var descendent in child.WalkTreeDown())
yield return descendent;
}
public static IEnumerable<DependencyObject> WalkTreeUp(this DependencyObject child)
{
for (; child != null; child = LogicalTreeHelper.GetParent(child))
yield return child;
}
public static void RemoveHyperlinks(this FlowDocument doc)
{
var allLinks = doc.WalkTreeDown().OfType<Hyperlink>().ToArray();
for (int iLink = allLinks.Length - 1; iLink >= 0; iLink--)
{
var link = allLinks[iLink];
var range = new TextRange(link.ContentStart.GetInsertionPosition(LogicalDirection.Backward), link.ContentEnd.GetInsertionPosition(LogicalDirection.Forward));
var first = link.Inlines.FirstInline;
var last = link.Inlines.LastInline;
link.Inlines.Add(new Run(" "));
link.Inlines.InsertBefore(first, new Run(" "));
var childRange = new TextRange(first.ContentStart, last.ContentEnd);
using (MemoryStream ms = new MemoryStream())
{
string format = DataFormats.XamlPackage;
childRange.Save(ms, format, true);
ms.Seek(0, SeekOrigin.Begin);
range.Load(ms, format);
}
}
}
}
我已经使用您的案例以及包含嵌入图像的超链接进行了测试。
当然,删除了超链接本身的下划线和格式。如果你愿意,你可以在之后添加它们。