WPF利用TextBlock實現(xiàn)查找結(jié)果高亮顯示效果
前言
在應(yīng)用開發(fā)過程中,經(jīng)常遇到這樣的需求:通過關(guān)鍵字查找數(shù)據(jù),把帶有關(guān)鍵字的數(shù)據(jù)顯示出來,同時在結(jié)果中高亮顯示關(guān)鍵字。在web開發(fā)中,只需在關(guān)鍵字上加一層標簽,然后設(shè)置標簽樣式就可以輕松實現(xiàn)。
在WPF中顯示文本內(nèi)容通常采用TextBlock控件,也可以采用類似的方式,通過內(nèi)聯(lián)流內(nèi)容元素Run達到同樣的效果:
<TextBlock FontSize="20">
<Run Text="Hel" /><Run Foreground="Red" Text="lo " /><Run Text="Word" />
</TextBlock>需要注意的是每個Run之間不要換行,如果換行的話,每個Run之間會有間隙,看起來像增加了空格。
通過這種方式實現(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"));這種方法雖然可以達到效果,但顯然與MVVM的思想不符。接下來本文介紹一種通過附加屬性實現(xiàn)TextBlock中指定內(nèi)容高亮。

技術(shù)要點與實現(xiàn)
通過TextEffect的PositionStart、PositionCount以及Foreground屬性設(shè)置字符串中需要高亮內(nèi)容的起始位置、長度以及高亮顏色。定義附加屬性允許TextBlock設(shè)置需要高亮的內(nèi)容位置以及顏色。
- 首先定義類
ColoredLettering(并不要求繼承DependencyObject)。 - 在
ColoredLettering中注冊自定義的附加屬性,注冊附加屬性方式與注冊依賴屬性類似,不過附加屬性是用DependencyProperty.RegisterAttached來注冊。 - 給附加屬性注冊屬性值變化事件,事件處理邏輯中設(shè)置
TextEffect的PositionStart、PositionCount以及Foreground實現(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)容,只需要對附加屬性進行改造,以支持傳入一組位置和顏色信息。
最后分享一個可以解析一組有限的HTML標記并顯示它們的WPF控件HtmlTextBlock ,通過這個控件也可以實現(xiàn)查找結(jié)果中高亮關(guān)鍵字,甚至支持指定內(nèi)容觸發(fā)事件做一些邏輯操作。
到此這篇關(guān)于WPF利用TextBlock實現(xiàn)查找結(jié)果高亮顯示效果的文章就介紹到這了,更多相關(guān)WPF TextBlock內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C# WPF如何反射加載Geometry幾何圖形數(shù)據(jù)圖標
這篇文章主要介紹了C# WPF如何反射加載Geometry幾何圖形數(shù)據(jù)圖標,幫助大家更好的理解和學習使用c#,感興趣的朋友可以了解下2021-03-03
C#自定義DataGridViewColumn顯示TreeView
我們可以自定義DataGridView的DataGridViewColumn來實現(xiàn)自定義的列,下面介紹一下如何通過擴展DataGridViewColumn來實現(xiàn)一個TreeViewColumn2015-12-12

