基本上我的问题是,当我尝试以编程方式将超过2个链接应用于ITextDocument时,如果用户编辑了内容,则会收到AccessViolationException。我已经根据Windows Phone(8.1)空白应用程序模板整理了一个简单的演示应用程序。
我添加到主页:
<StackPanel Margin="19,0,0,0">
<Button
Content="Apply Links"
Click="Button_Click"
/>
<RichEditBox
x:Name="RtfBox"
Height="300"
Loaded="RtfBox_Loaded"
Margin="0,0,19,0"
TextWrapping="Wrap"
/>
</StackPanel>
对于我添加的同一页面后面的代码(使用不包含的语句):
private void RtfBox_Loaded(object sender, RoutedEventArgs e)
{
//RtfBox.Document.SetText(TextSetOptions.None, "Links to demo, example, test. More links to demo, demo, example, test and test.");
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var pages = new Dictionary<Guid, string> { { Guid.NewGuid(), "demo" }, { Guid.NewGuid(), "example" }, { Guid.NewGuid(), "test" } };
// NOTE: Avoid performance implications of many small updates
RtfBox.Document.BatchDisplayUpdates();
ITextRange range;
foreach (var page in pages)
{
var link = string.Format("\"richtea.demo://pages/{0}\"", page.Key);
var skip = 0;
while ((range = RtfBox.Document.GetRange(skip, TextConstants.MaxUnitCount)).FindText(page.Value, TextConstants.MaxUnitCount, FindOptions.None) != 0)
{
if (range.Link == "")
{
// TODO: Stop this throw exceptions
System.Diagnostics.Debug.WriteLine("Setting text at position {0} to link: '{1}'.", range.StartPosition, link);
range.Link = link;
}
skip = range.EndPosition;
}
}
RtfBox.Document.ApplyDisplayUpdates();
}
如果你开始这样做并输入类似&#34;链接到演示页面&#34;并单击按钮,它正确成为一个链接。您可以继续放置相同的文本并单击按钮,它将继续工作。
但是,如果您为 demo ,示例或测试(我的关键字)并按下按钮,在AccessViolationException
设置range.Link = link
时出现错误。值得注意的是,如果在调试时检查,则实际设置了range.Link属性。
更有趣的是,如果您取消注释RtfBox_Loaded
的内容,并立即运行该应用并点击该按钮,则可以正常处理。所以它似乎与RichEditBox上设置的选择有关?我在尝试使用链接之前尝试禁用控件,但这对我没有帮助。
其他一些让我更难诊断问题的事情包括:
另外,对于记录,我尝试对大量进行所有更新的原因,而不是用户输入的原因是我不想在重命名笔记时处理清理或已删除,我不想在编辑时将这些链接保存或保存,但我可以使用后者。
答案 0 :(得分:0)
此解决方案由posted on the MSDN forums Eric Fleck提供,并为我工作:
RtfBox.Document.Selection.StartPosition = RtfBox.Document.Selection.EndPosition = range.StartPosition;
range.Link = link;
RtfBox.Document.Selection.StartPosition = RtfBox.Document.Selection.EndPosition = range.EndPosition;
在设置的每个链接周围做这件事似乎很重要,因为除非我非常错误,否则我在更新所有链接之前尝试了这个,但它没有帮助。
我还没有使用将选择恢复到原始位置的能力,但我可能希望将来使用,所以我创建了这个小实用程序类。另外,我可以将这样的地方包装在using()块中以获得一些语法糖。
public static class ITextDocumentExtensions
{
public static IDisposable SuppressSelection(this ITextDocument document)
{
var start = document.Selection.StartPosition;
var end = document.Selection.EndPosition;
var disposable = new ActionDisposable(() => document.Selection.SetRange(start, end));
document.Selection.SetRange(0, 0);
return disposable;
}
private sealed class ActionDisposable : IDisposable
{
private readonly Action dispose;
public ActionDisposable(Action dispose)
{
this.dispose = dispose;
}
public void Dispose()
{
dispose();
}
}
}
允许我写
using (RtfBox.Document.SuppressSelection())
{
range.Link = link;
}