如何跟踪TextPointer在WPF RichTextBox的? [英] How to keep track of TextPointer in WPF RichTextBox?

查看:389
本文介绍了如何跟踪TextPointer在WPF RichTextBox的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图让我绕了WPF的RichTextBox TextPointer类的头。

I'm trying to get my head around the TextPointer class in a WPF RichTextBox.

我希望能够保持他们的跟踪,这样我就可以联想信息与文本的地方。

I would like to be able to keep track of them so that I can associate information with areas in the text.

我目前一个非常简单的例子努力试图找出到底是怎么回事。在PreviewKeyDown事件,我存储插入符的位置,然后在PreviewKeyUp事件我创建基础上,前,后尖位置一个TextRange。下面是一个代码示例,说明了什么,我试图做的:

I am currently working with a very simple example to try and figure out what is going on. In the PreviewKeyDown event I am storing the caret position and then in the PreviewKeyUp event I am creating a TextRange based on the before and after caret positions. Here is a code sample that illustrates what I am trying to do:

// The caret position before typing
private TextPointer caretBefore = null;

private void rtbTest_PreviewKeyDown(object sender, KeyEventArgs e)
{
    // Store caret position
    caretBefore = rtbTest.CaretPosition;
}

private void rtbTest_PreviewKeyUp(object sender, KeyEventArgs e)
{
    // Get text between before and after caret positions
    TextRange tr = new TextRange(caretBefore, rtbTest.CaretPosition);
    MessageBox.Show(tr.Text);
}

的问题是,我得到的文本是空白。例如,如果我输入字符'a',那么我希望找到文本的a设置TextRange。

The problem is that the text that I get is blank. For example, if I type the character 'a' then I would expect to find the text "a" in the TextRange.

有谁知道是怎么回事了?这可能是很简单的东西,但我已经花了一个下午的越来越行不通。

Does anyone know what is going wrong? It could be something very simple but I've spent an afternoon getting nowhere.

我试图拥抱新的WPF技术,但发现,尤其在RichTextBox是如此复杂它甚至使简单的做这样的事情很难。如果任何人有做解释TextPointer一个好工作的任何链接,我将不胜感激,如果你可以让我知道。

I am trying to embrace the new WPF technology but find that the RichTextBox in particular is so complicated that it makes even doing simple things like this difficult. If anyone has any links that do a good job of explaining the TextPointer, I would appreciate it if you can let me know.

推荐答案

当您添加并从FlowDocument的删除文本,所有的TextPointers基于一些旨在使他们留在接近相同的地方尽可能启发式的调整自己的位置。

When you add and remove text from a FlowDocument, all the TextPointers adjust their position based on a number of heuristics designed to make them stay in as close to the same "place" as possible.

有关删除这很简单:如果TextPointer是被删除的内容,它结束了betweem已被周围已删除的文本字符。但是,对于插入它不是那么简单:当文本或其它元素插入的FlowDocument正是在现有的TextPointer,应TextPointer前或插入的文本之后结束了? TextPointer有一个名为LogicalDirection控制这个属性。

For deletions this is simple: If the TextPointer is in the deleted text, it ends up betweem the characters that had been surrounding the deleted text. But for insertions it is not so simple: When text or other elements are inserted into a FlowDocument exactly at an existing TextPointer, should the TextPointer end up before or after the inserted text? TextPointer has a property called "LogicalDirection" that controls this.

什么是你的情况发生的是,caretBefore的位置正在捕获正是TextPosition那里的类型化字符插入,并在测试情况下,您LogicalDirection是LogicalDirection.Forward。插入字符因此,当您的caretBefore已经结束了的之后的插入的字符,这与TextPosition给你一个空的TextRange一致。

What is happening in your case is that the "caretBefore" position you are capturing is exactly the TextPosition where the typed character is inserted, and in your test cases your LogicalDirection is LogicalDirection.Forward. Thus when the character is inserted, your "caretBefore" is ending up after the inserted character, which coincides with TextPosition giving you an empty TextRange.

如何获取一个TextPointer得到分配给它一个LogicalDirection?如果您在RichTextBox的点击设置插入符位置,点击被解释为两个字符之间。如果您单击的实际点是在第二个字符,LogicalDirection设置为前进,但如果你点击的实际点是第一个字符,LogicalDirection设置为落后。

How does a TextPointer get a LogicalDirection assigned to it? If you click on a the RichTextBox to set the caret position, the click is interpreted as being between two characters. If the actual point you clicked was on the second character, LogicalDirection is set to Forward, but if the actual point you clicked on was the first character, LogicalDirection is set to Backward.

试试这个实验:


  1. 设置你的字号=40,并在构造函数中的文本ABCD
  2. 点击在b的右侧,然后键入b和C.该之间LogicalDirection的X是退,让你的beforeCaret中的X和你的消息框显示之前结束在X。

  3. 单击在C的左侧,然后键入b和C.该之间LogicalDirection的X是前进,让你的beforeCaret后结束X和你的消息框为空

这行为是违反直觉的:当你不知道LogicalDirection存在,你会觉得。在b或C的左边的右边的点击会给你一模一样的插入位置

This behaviour is counterintuitive: When you don't know that LogicalDirection exists, you would think that clicking on the right-hand side of the B or the left-hand side of the C would give you exactly the same caret position.

请注意:一个简单的方法预想正在发生的事情是指挥你的MessageBox.Show,而是做了 caretBefore.InsertTextInRun(^);

Note: An easy way to visualize what is going on is to command out your MessageBox.Show and instead do a caretBefore.InsertTextInRun("^");

你如何达到你所需要的结果呢? LogicalDirection是只读。一种方法是使用的TextRange强制的TextPointer建设与向后LogicalDirection:

How do you achieve the result you need? LogicalDirection is read-only. One way is to use TextRange to force the construction of a TextPointer with a LogicalDirection of Backward:

caretBefore = new TextRange(caretBefore, caretBefore.DocumentEnd).Start;

在PreviewKeyDown执行此操作。如果等到PreviewKeyUp它已经太晚了:caretBefore已移动。这工作,因为据我所知,一个非空的TextRange的开始总有向后LogicalDirection。

Do this in PreviewKeyDown. If you wait until PreviewKeyUp it is already too late: caretBefore has moved. This works because as far as I can tell, the Start of a non-empty TextRange always has a LogicalDirection of Backward.

另一个选择是保存符号从偏移始文档(注意,这不是一个字符的偏移!)。在这种情况下,你可以存储在PreviewKeyDown偏移量:

Another option is to save the symbol offset from the beginning of the document (note that this is not a character offset!). In this case you could store the offset in PreviewKeyDown:

caretBeforeOffset = caretBefore.DocumentStart.OffsetToPosition(caretBefore);

和重置caretBefore相同的符号PreviewKeyUp偏移:

and reset caretBefore to the same symbol offset in PreviewKeyUp:

caretBefore = caretBefore.DocumentStart.GetPositionAtOffset(caretBeforeOffset,
                                                            LogicalDirection.Forward);



虽然这个作品它并不像一般的强迫你的TextPointer拥有的向后LogicalDirection:任何文本早些时候PreviewKeyDown和PreviewKeyUp之间的文档中的更改将导致符号偏移计算找到​​了错误的位置,这是什么TextPointers设计摆在首位来解决。

Although this works it is not as general as forcing your TextPointer to have a LogicalDirection of Backward: Any text changes earlier in the document between the PreviewKeyDown and PreviewKeyUp will cause the symbol offset calculation to find the wrong location, which is what TextPointers were designed to fix in the first place.

我不知道有什么好的资源,学习TextPointers除了阅读文档,并和他们一起玩,这就是你已经做什么。

I don't know of any good resources for learning about TextPointers except for reading the documentation and playing with them, which is exactly what you have already been doing.

这篇关于如何跟踪TextPointer在WPF RichTextBox的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆