如果我理解你的問題正確,要突出顯示當前選擇的含第(插入符的當前位置)。所以很顯然,每次選擇更改時都必須獲取包含的段落。然後,您可以將Foreground
更改爲Brushes.Red
。幸運的是,包含的段落似乎被TextPointer引用,並且發現它的過程幾乎是立即進行的。 (TextPointer有一個名爲Paragraph
的屬性)。這裏是詳細的代碼:
Paragraph p = null;
//Suppose rtb is the name of your RichtTextBox
private void UpdateContainingBlockState() {
if (p != rtb.Selection.Start.Paragraph){
if (p != null) p.Foreground = Brushes.Black;
p = rtb.Selection.Start.Paragraph;
if (p != null) p.Foreground = Brushes.Red;
}
}
//The SelectionChanged event handler for your RichTextBox
private void selectionChangedHandler(object sender, RoutedEventArgs e){
UpdateContainingBlockState();
}
更改選擇的頻率相當高(每次按幾乎可以導致選擇更改的鍵)。因此,如果您的文檔很大,並且您在輸入時意識到性能不佳,那麼現在是切換到下一個更復雜的代碼的時候了。您還可以嘗試使用線程方法(或使用任務)將UpdateContainingBlockState()
調用放入另一個線程,但要注意跨線程訪問。這裏我用了不同的方法,這個想法是調用UpdateContainingBlockState()
在正確的時間,即當實際的選擇可以改變段落之間跳躍。當輸入正常的可打印字符,則選擇將始終處於當前段落(所以我們並不需要調用UpdateContainingBlockState()
)當你鍵入輸入鍵,除非。通常我們會在用戶輸入一個控制鍵(箭頭鍵,home,end,Enter,...)時調用該方法。如果RichTextBox聚焦並且用戶在RichTextBox上單擊鼠標,我們也應該調用該方法。你可以看到,幾乎所有鍵入的字符都不會觸發調用該方法,因此它會比上面的代碼提高性能(當然,只有在文檔很大時纔可以實現)。下面是詳細代碼:
//should add this using at the beginning
using System.Runtime.InteropServices;
[DllImport("user32")]
private static extern int MapVirtualKey(int ucode, int mapType);
//The KeyUp event handler for your RichTextBox
private void keyUp_Handler(object sender, KeyEventArgs e){
if (char.IsControl((char) MapVirtualKey(KeyInterop.VirtualKeyFromKey(e.Key),0x2)))
UpdateContainingBlockState();
}
//The PreviewMouseUp event handler for your RichTextBox
private void previewMouseUp_Handler(object sender, MouseButtonEventArgs e){
//UpdateContainingBlockState();
//Calling UpdateContainingBlockState() directly will cause a small issue
//So we use this instead
Task.Run(() => Dispatcher.Invoke(() => UpdateContainingBlockState()));
}
//The GotKeyboardFocus event handler for your RichTextBox
private void gotKeyboardFocus_Handler(object sender,
KeyboardFocusChangedEventArgs e){
UpdateContainingBlockState();
}