遇到此需求,但找不到任何合适的解决方案。 (使用 TextBox 进行绑定、动态突出显示、多次点击和颜色等)这显然可以扩展以满足您的需求。这引用了几个扩展方法,它们从 UIElement 的装饰层添加/删除指定类型 T 的装饰器。
public class HighlightRule
{
public SolidColorBrush Brush { get; set; }
public string MatchText { get; set; }
public HighlightRule(SolidColorBrush solidColorBrush, string matchText)
{
Brush = solidColorBrush;
MatchText = matchText;
}
public HighlightRule(Color color, string matchText)
{
Brush = new SolidColorBrush(color);
MatchText = matchText;
}
public HighlightRule()
{
MatchText = null;
Brush = Brushes.Black;
}
}
public class HighlightTextBox : TextBox
{
public List<HighlightRule> HighlightRules
{
get { return ( List<HighlightRule>)GetValue(HighlightRulesProperty); }
set { SetValue(HighlightRulesProperty, value); }
}
// Using a DependencyProperty as the backing store for HighlightRules. This enables animation, styling, binding, etc...
public static readonly DependencyProperty HighlightRulesProperty =
DependencyProperty.Register("HighlightRules", typeof(List<HighlightRule>), typeof(HighlightTextBox), new FrameworkPropertyMetadata(new List<HighlightRule>(), new PropertyChangedCallback(HighlightRulesChanged)));
private static void HighlightRulesChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
HighlightTextBox tb = (HighlightTextBox)sender;
tb.ApplyHighlights();
}
public HighlightTextBox() : base()
{
this.Loaded += HighlightTextBox_Loaded;
}
protected override void OnTextChanged(TextChangedEventArgs e)
{
base.OnTextChanged(e);
ApplyHighlights();
}
private void HighlightTextBox_Loaded(object sender, RoutedEventArgs e)
{
ApplyHighlights();
}
static HighlightTextBox()
{
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
}
public void ApplyHighlights()
{
this.TryRemoveAdorner<GenericAdorner>();
foreach(HighlightRule rule in HighlightRules)
{
if (!string.IsNullOrEmpty(rule.MatchText) && !string.IsNullOrEmpty(Text) &&
Text.ToLower().Contains(rule.MatchText.ToLower()))
{
if (base.ActualHeight != 0 && base.ActualWidth != 0)
{
int indexOf = 0;
do
{
indexOf = Text.IndexOf(rule.MatchText, indexOf);
if (indexOf == -1) break;
Rect rect = base.GetRectFromCharacterIndex(indexOf);
Rect backRect = base.GetRectFromCharacterIndex(indexOf + rule.MatchText.Length - 1, true);
this.TryAddAdorner<GenericAdorner>(new GenericAdorner(this, new Rectangle()
{ Height = rect.Height, Width = backRect.X - rect.X, Fill = rule.Brush, Opacity = 0.5 }));
indexOf++;
} while (true);
}
}
}
}
}
GenericAdorner / 辅助方法
public class GenericAdorner : Adorner
{
private readonly UIElement adorner;
private readonly Point point;
public GenericAdorner(UIElement targetElement, UIElement adorner, Point point) : base(targetElement)
{
this.adorner = adorner;
if (adorner != null)
{
AddVisualChild(adorner);
}
this.point = point;
}
protected override int VisualChildrenCount
{
get { return adorner == null ? 0 : 1; }
}
protected override Size ArrangeOverride(Size finalSize)
{
if (adorner != null)
{
adorner.Arrange(new Rect(point, adorner.DesiredSize));
}
return finalSize;
}
protected override Visual GetVisualChild(int index)
{
if (index == 0 && adorner != null)
{
return adorner;
}
return base.GetVisualChild(index);
}
}
public static void TryRemoveAdorner<T>(this UIElement element)
where T:Adorner
{
AdornerLayer layer = AdornerLayer.GetAdornerLayer(element);
if (layer != null)
layer.RemoveAdorners<T>(element);
}
public static void RemoveAdorners<T>(this AdornerLayer layer, UIElement element)
where T : Adorner
{
var adorners = layer.GetAdorners(element);
if (adorners == null) return;
for (int i = adorners.Length -1; i >= 0; i--)
{
if (adorners[i] is T)
layer.Remove(adorners[i]);
}
}
public static void TryAddAdorner<T>(this UIElement element, Adorner adorner)
where T: Adorner
{
AdornerLayer layer = AdornerLayer.GetAdornerLayer(element);
if (layer != null)
try
{
layer.Add(adorner);
}
catch (Exception) { }
}
public static bool HasAdorner<T>(this AdornerLayer layer, UIElement element) where T : Adorner
{
var adorners = layer.GetAdorners(element);
if (adorners == null) return false;
for (int i = adorners.Length - 1; i >= 0; i--)
{
if (adorners[i] is T)
return true;
}
return false;
}
public static void RemoveAdorners(this AdornerLayer layer, UIElement element)
{
var adorners = layer.GetAdorners(element);
if (adorners == null) return;
foreach (Adorner remove in adorners)
layer.Remove(remove);
}
XAML
<local:HighlightTextBox FontFamily="Calibri" Foreground="Blue" FontSize="12" Text="Hello you!! And also hello to you!" TextWrapping="Wrap" Margin="5,3,0,0">
<local:HighlightTextBox.HighlightRules>
<local:HighlightRule Brush="Red" MatchText="you"/>
<local:HighlightRule Brush="Blue" MatchText="also"/>
</local:HighlightTextBox.HighlightRules>
</local:HighlightTextBox>
外观