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

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

