Dan*_*rik 14 wpf highlighting textblock
我有TextBlock动态添加Inlines(基本上是一堆斜体或粗体的Run对象).
在我的应用程序中,我有搜索功能.
我希望能够突出显示正在搜索的TextBlock文本.
通过突出显示我的意思是更改TextBlock文本颜色的某些部分(请记住,它可能一次突出显示几个不同的Run对象).
但它接缝非常不稳定:(
有没有简单的方法来解决这个问题?
dth*_*her 17
此问题类似于如何在突出显示的查询字词的WPF项目控件中显示搜索结果
在回答这个问题时,我提出了一种使用IValueConverter的方法.转换器获取文本片段,将其格式化为有效的XAML标记,并使用XamlReader将标记实例化为框架对象.
完整的解释相当长,所以我把它发布到我的博客:突出显示WPF TextBlock中的查询条款
Syn*_*les 10
我接受了dthrasers的回答,并且需要一个XML解析器.他很好地解释了他博客中的每一个部分,但是这并没有要求我添加任何额外的库,这就是我如何做到的.
第一步,制作转换器类:
class StringToXamlConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string input = value as string;
if (input != null)
{
var textBlock = new TextBlock();
textBlock.TextWrapping = TextWrapping.Wrap;
string escapedXml = SecurityElement.Escape(input);
while (escapedXml.IndexOf("|~S~|") != -1) {
//up to |~S~| is normal
textBlock.Inlines.Add(new Run(escapedXml.Substring(0, escapedXml.IndexOf("|~S~|"))));
//between |~S~| and |~E~| is highlighted
textBlock.Inlines.Add(new Run(escapedXml.Substring(escapedXml.IndexOf("|~S~|") + 5,
escapedXml.IndexOf("|~E~|") - (escapedXml.IndexOf("|~S~|") + 5)))
{ FontWeight = FontWeights.Bold, Background= Brushes.Yellow });
//the rest of the string (after the |~E~|)
escapedXml = escapedXml.Substring(escapedXml.IndexOf("|~E~|") + 5);
}
if (escapedXml.Length > 0)
{
textBlock.Inlines.Add(new Run(escapedXml));
}
return textBlock;
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException("This converter cannot be used in two-way binding.");
}
}
Run Code Online (Sandbox Code Playgroud)
第二步:使用ContentBlock而不是TextBlock.将字符串(您将用于textBlock)传递给内容块,如下所示:
<ContentControl
Margin="7,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Content="{Binding Description, Converter={StaticResource CONVERTERS_StringToXaml}, Mode=OneTime}">
</ContentControl>
Run Code Online (Sandbox Code Playgroud)
第三步:确保传入的测试用|~S~|和标记|~E~|.让突出显示开始!
注意:
您可以更改运行中的样式以确定文本突出显示的内容和方式
确保将Converter类添加到命名空间和资源中.这可能还需要重建才能正常工作.
奇怪的是,我最近写了一篇文章来解决同样的问题。这是一个具有相同的属性为TextBlock的自定义控件(所以你可以互换是出去TextBlock无论你需要它),它有一个额外的属性,您可以绑定到叫HighLightText,何地的价值HighLightText在被发现mainText属性(不区分大小写),突出显示。
这是一个相当直接的控件创建,你可以在这里找到这篇文章:
以及作为解决方案的完整代码:
Text="blabla"TextBlock的常规属性。而是将您的文本绑定到HighlightTermBehavior.Text="blabla".<TextBlock local:HighlightTermBehavior.TermToBeHighlighted="{Binding MyTerm}"
local:HighlightTermBehavior.Text="{Binding MyText}" />
Run Code Online (Sandbox Code Playgroud)
或硬编码
<TextBlock local:HighlightTermBehavior.TermToBeHighlighted="highlight this"
local:HighlightTermBehavior.Text="bla highlight this bla" />
Run Code Online (Sandbox Code Playgroud)
AddPartToTextBlock()对于突出显示的文本的非突出AddHighlightedPartToTextBlock()显示的文本。 FontWeights.ExtraBold,非突出显示的文本是FontWeights.Light。public static class HighlightTermBehavior
{
public static readonly DependencyProperty TextProperty = DependencyProperty.RegisterAttached(
"Text",
typeof(string),
typeof(HighlightTermBehavior),
new FrameworkPropertyMetadata("", OnTextChanged));
public static string GetText(FrameworkElement frameworkElement) => (string) frameworkElement.GetValue(TextProperty);
public static void SetText(FrameworkElement frameworkElement, string value) => frameworkElement.SetValue(TextProperty, value);
public static readonly DependencyProperty TermToBeHighlightedProperty = DependencyProperty.RegisterAttached(
"TermToBeHighlighted",
typeof(string),
typeof(HighlightTermBehavior),
new FrameworkPropertyMetadata("", OnTextChanged));
public static string GetTermToBeHighlighted(FrameworkElement frameworkElement)
{
return (string) frameworkElement.GetValue(TermToBeHighlightedProperty);
}
public static void SetTermToBeHighlighted(FrameworkElement frameworkElement, string value)
{
frameworkElement.SetValue(TermToBeHighlightedProperty, value);
}
private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is TextBlock textBlock)
SetTextBlockTextAndHighlightTerm(textBlock, GetText(textBlock), GetTermToBeHighlighted(textBlock));
}
private static void SetTextBlockTextAndHighlightTerm(TextBlock textBlock, string text, string termToBeHighlighted)
{
textBlock.Text = string.Empty;
if (TextIsEmpty(text))
return;
if (TextIsNotContainingTermToBeHighlighted(text, termToBeHighlighted))
{
AddPartToTextBlock(textBlock, text);
return;
}
var textParts = SplitTextIntoTermAndNotTermParts(text, termToBeHighlighted);
foreach (var textPart in textParts)
AddPartToTextBlockAndHighlightIfNecessary(textBlock, termToBeHighlighted, textPart);
}
private static bool TextIsEmpty(string text)
{
return text.Length == 0;
}
private static bool TextIsNotContainingTermToBeHighlighted(string text, string termToBeHighlighted)
{
return text.Contains(termToBeHighlighted, StringComparison.Ordinal) == false;
}
private static void AddPartToTextBlockAndHighlightIfNecessary(TextBlock textBlock, string termToBeHighlighted, string textPart)
{
if (textPart == termToBeHighlighted)
AddHighlightedPartToTextBlock(textBlock, textPart);
else
AddPartToTextBlock(textBlock, textPart);
}
private static void AddPartToTextBlock(TextBlock textBlock, string part)
{
textBlock.Inlines.Add(new Run {Text = part, FontWeight = FontWeights.Light});
}
private static void AddHighlightedPartToTextBlock(TextBlock textBlock, string part)
{
textBlock.Inlines.Add(new Run {Text = part, FontWeight = FontWeights.ExtraBold});
}
public static List<string> SplitTextIntoTermAndNotTermParts(string text, string term)
{
if (text.IsNullOrEmpty())
return new List<string>() {string.Empty};
return Regex.Split(text, $@"({Regex.Escape(term)})")
.Where(p => p != string.Empty)
.ToList();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
25302 次 |
| 最近记录: |