WPF利用TextBlock實(shí)現(xiàn)查找結(jié)果高亮顯示效果
前言
在應(yīng)用開發(fā)過程中,經(jīng)常遇到這樣的需求:通過關(guān)鍵字查找數(shù)據(jù),把帶有關(guān)鍵字的數(shù)據(jù)顯示出來,同時在結(jié)果中高亮顯示關(guān)鍵字。在web開發(fā)中,只需在關(guān)鍵字上加一層標(biāo)簽,然后設(shè)置標(biāo)簽樣式就可以輕松實(shí)現(xiàn)。
在WPF中顯示文本內(nèi)容通常采用TextBlock
控件,也可以采用類似的方式,通過內(nèi)聯(lián)流內(nèi)容元素Run
達(dá)到同樣的效果:
<TextBlock FontSize="20"> <Run Text="Hel" /><Run Foreground="Red" Text="lo " /><Run Text="Word" /> </TextBlock>
需要注意的是每個Run
之間不要換行,如果換行的話,每個Run
之間會有間隙,看起來像增加了空格。
通過這種方式實(shí)現(xiàn)查找結(jié)果中高亮關(guān)鍵字,需要把查找結(jié)果拆分成三部分,然后綁定到Run
元素的Text
屬性,或者在后臺代碼中使用TextBlock
的Inlines
屬性添加Run
元素
textBlock1.Inlines.Add(new Run("hel")); textBlock1.Inlines.Add(new Run("lo ") { Foreground=new SolidColorBrush(Colors.Red)}); textBlock1.Inlines.Add(new Run("world"));
這種方法雖然可以達(dá)到效果,但顯然與MVVM的思想不符。接下來本文介紹一種通過附加屬性實(shí)現(xiàn)TextBlock
中指定內(nèi)容高亮。
技術(shù)要點(diǎn)與實(shí)現(xiàn)
通過TextEffect
的PositionStart
、PositionCount
以及Foreground
屬性設(shè)置字符串中需要高亮內(nèi)容的起始位置、長度以及高亮顏色。定義附加屬性允許TextBlock
設(shè)置需要高亮的內(nèi)容位置以及顏色。
- 首先定義類
ColoredLettering
(并不要求繼承DependencyObject
)。 - 在
ColoredLettering
中注冊自定義的附加屬性,注冊附加屬性方式與注冊依賴屬性類似,不過附加屬性是用DependencyProperty.RegisterAttached
來注冊。 - 給附加屬性注冊屬性值變化事件,事件處理邏輯中設(shè)置
TextEffect
的PositionStart
、PositionCount
以及Foreground
實(shí)現(xiàn)內(nèi)容高亮。
public class ColoredLettering { public static void SetColorStart(TextBlock textElement, int value) { textElement.SetValue(ColorStartProperty, value); } public static int GetColorStart(TextBlock textElement) { return (int)textElement.GetValue(ColorStartProperty); } // Using a DependencyProperty as the backing store for ColorStart. This enables animation, styling, binding, etc... public static readonly DependencyProperty ColorStartProperty = DependencyProperty.RegisterAttached("ColorStart", typeof(int), typeof(ColoredLettering), new FrameworkPropertyMetadata(0, OnColorStartChanged)); private static void OnColorStartChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TextBlock textBlock = d as TextBlock; if (textBlock != null) { if (e.NewValue == e.OldValue) return; if (e.NewValue is int) { int count = GetColorLength(textBlock); Brush brush = GetForeColor(textBlock); if ((int)e.NewValue <= 0 || count <= 0 || brush == TextBlock.ForegroundProperty.DefaultMetadata.DefaultValue) return; if (textBlock.TextEffects.Count != 0) { textBlock.TextEffects.Clear(); } TextEffect textEffect = new TextEffect() { Foreground = brush, PositionStart = (int)e.NewValue, PositionCount = count }; textBlock.TextEffects.Add(textEffect); } } } public static void SetColorLength(TextBlock textElement, int value) { textElement.SetValue(ColorLengthProperty, value); } public static int GetColorLength(TextBlock textElement) { return (int)textElement.GetValue(ColorLengthProperty); } // Using a DependencyProperty as the backing store for ColorStart. This enables animation, styling, binding, etc... public static readonly DependencyProperty ColorLengthProperty = DependencyProperty.RegisterAttached("ColorLength", typeof(int), typeof(ColoredLettering), new FrameworkPropertyMetadata(0, OnColorLengthChanged)); private static void OnColorLengthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TextBlock textBlock = d as TextBlock; if (textBlock != null) { if (e.NewValue == e.OldValue) return; if (e.NewValue is int) { int start = GetColorStart(textBlock); Brush brush = GetForeColor(textBlock); if ((int)e.NewValue <= 0 || start <= 0 || brush == TextBlock.ForegroundProperty.DefaultMetadata.DefaultValue) return; if (textBlock.TextEffects.Count != 0) { textBlock.TextEffects.Clear(); } TextEffect textEffect = new TextEffect() { Foreground = brush, PositionStart = start, PositionCount = (int)e.NewValue }; textBlock.TextEffects.Add(textEffect); } } } public static void SetForeColor(TextBlock textElement, Brush value) { textElement.SetValue(ColorStartProperty, value); } public static Brush GetForeColor(TextBlock textElement) { return (Brush)textElement.GetValue(ForeColorProperty); } // Using a DependencyProperty as the backing store for ForeColor. This enables animation, styling, binding, etc... public static readonly DependencyProperty ForeColorProperty = DependencyProperty.RegisterAttached("ForeColor", typeof(Brush), typeof(ColoredLettering), new PropertyMetadata(TextBlock.ForegroundProperty.DefaultMetadata.DefaultValue, OnForeColorChanged)); private static void OnForeColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TextBlock textBlock = d as TextBlock; if (textBlock != null) { if (e.NewValue == e.OldValue) return; if (e.NewValue is Brush) { int start = GetColorStart(textBlock); int count = GetColorLength(textBlock); if (start <= 0 || count <= 0) return; if (textBlock.TextEffects.Count != 0) { textBlock.TextEffects.Clear(); } TextEffect textEffect = new TextEffect() { Foreground = (Brush)e.NewValue, PositionStart = start, PositionCount = count }; textBlock.TextEffects.Add(textEffect); } } } }
調(diào)用時只需在TextBlock
指定需要高亮內(nèi)容的開始位置,內(nèi)容長度以及高亮顏色即可。
<TextBlock local:ColoredLettering.ColorLength="{Binding Count}" local:ColoredLettering.ColorStart="{Binding Start}" local:ColoredLettering.ForeColor="{Binding ForeColor}" FontSize="20" Text="Hello World" />
總結(jié)
本文介紹的方法只是高亮第一個匹配到的關(guān)鍵字,如果需要高亮匹配到的所有內(nèi)容,只需要對附加屬性進(jìn)行改造,以支持傳入一組位置和顏色信息。
最后分享一個可以解析一組有限的HTML標(biāo)記并顯示它們的WPF控件HtmlTextBlock ,通過這個控件也可以實(shí)現(xiàn)查找結(jié)果中高亮關(guān)鍵字,甚至支持指定內(nèi)容觸發(fā)事件做一些邏輯操作。
到此這篇關(guān)于WPF利用TextBlock實(shí)現(xiàn)查找結(jié)果高亮顯示效果的文章就介紹到這了,更多相關(guān)WPF TextBlock內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#使用StructLayout特性來控制內(nèi)存結(jié)構(gòu)的操作代碼
在C#中,內(nèi)存布局對于性能優(yōu)化和與非托管代碼的互操作性至關(guān)重要,StructLayout特性允許開發(fā)者控制結(jié)構(gòu)在內(nèi)存中的布局方式,本文給大家介紹了C#使用StructLayout特性來控制內(nèi)存結(jié)構(gòu)的操作,需要的朋友可以參考下2024-10-10C#正則表達(dá)式(Regex類)用法實(shí)例總結(jié)
正則表達(dá)式的主要作用是驗(yàn)證字符串的值是否滿足一定的規(guī)則,在頁面輸入數(shù)據(jù)驗(yàn)證方面的應(yīng)用比較多,下面這篇文章主要給大家介紹了關(guān)于C#正則表達(dá)式(Regex類)用法的相關(guān)資料,需要的朋友可以參考下2022-08-08關(guān)于C#操作文件路徑(Directory)的常用靜態(tài)方法詳解
這篇文章主要給大家介紹了關(guān)于C#操作文件路徑(Directory)的常用靜態(tài)方法,Directory類位于System.IO 命名空間,Directory類提供了在目錄和子目錄中進(jìn)行創(chuàng)建移動和列舉操作的靜態(tài)方法,需要的朋友可以參考下2021-08-08C#基礎(chǔ):Dispose()、Close()、Finalize()的區(qū)別詳解
本篇文章是對c#中的Dispose()、Close()、Finalize()的區(qū)別進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05