基本的に私の問題は、ユーザーがコンテンツを編集した場合に、ITextDocument に 2 つ以上のリンクをプログラムで適用しようとすると、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();
}
これを起動して「デモページへのリンク」などと入力してボタンをクリックすると、正しくリンクになります。同じテキストを入力してボタンをクリックし続けると、引き続き機能します。
ただし、単語demo、exampleまたはtest (私のキーワード)を 3 つ以上 (何らかの理由で常に 3 つ以上)入力してボタンを押すと、 AccessViolationException
on settingでエラーが発生しますrange.Link = link
。デバッグ中に確認すると、 range.Link プロパティが実際に設定されていることに注意してください。
さらに興味深いことに、 のコンテンツのコメントを外しRtfBox_Loaded
、アプリを実行してすぐにボタンをクリックすると、問題なく処理されます。つまり、RichEditBox で設定された選択に関連しているように見えますか? リンクを適用する前にコントロールを無効にしてみましたが、うまくいきません。
ここで問題を診断するのが難しくなった他のいくつかのことには、次のものがあります。
- 行ごとにデバッグしている場合はより頻繁に機能するように見えるので、タイミングも関係している可能性があります
- どうやら UI スレッドではなく ITextDocument を使用できない (COM オブジェクトがキャストに失敗する) ため、非同期の方がより良いアプローチであると思われますが、ここでは成功していません。
また、記録のために、ユーザーが入力するのではなく、すべての更新をまとめて実行しようとしている理由は、メモの名前が変更されたり削除されたりしたときにクリーンアップを処理したくないためです。編集時または保存時にこれらのリンクが本当に欲しいのですが、後で一緒に暮らすことができます。