我想在WPF ItemsControl中显示搜索结果,并突出显示查询字词。
我使用的搜索引擎,Lucene.Net和Highlighter插件,返回字符串,查询条件标记如下:
...these <Bold>results</Bold> were found to be statistically significant...
我可以指示Highlighter插件使用任何标记标记来包装查询术语。我不限于上面例子中的<Bold>
标签。对于WPF,我可能会使这些<Run/>
元素附加一个样式。
挑战是获取我已经给出的字符串并将其呈现为我在搜索结果中使用的数据模板中的“实际XAML”。换句话说,我想看到这样的事情:
......这些结果被发现具有统计学意义......
但我正在努力解决如何在数据模板中将数据绑定与XAML字符串的动态呈现相结合的问题。这里最好的方法是什么?
XamlReader.Load()
?我拿了dthrasers answer并且需要一个XML解析器。他很好地解释了his blog中的每一个部分,但是这并没有要求我添加任何额外的库,这就是我如何做到的。
第一步,制作转换器类:
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.");
}
}
第二步:使用ContentBlock而不是TextBlock。将字符串(您将用于textBlock)传递给内容块,如下所示:
<ContentControl
Margin="7,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Content="{Binding Description, Converter={StaticResource CONVERTERS_StringToXaml}, Mode=OneTime}">
</ContentControl>
第三步:确保传入的测试是用|~S~|
和|~E~|
标记的。让突出显示开始!
笔记: 您可以更改运行中的样式以确定文本突出显示的内容和方式 确保将Converter类添加到命名空间和资源中。这可能还需要重建才能正常工作。
我找到了一种使用自定义IValueConverter将突出显示应用于搜索结果的方法。转换器获取文本片段,将其格式化为有效的XAML标记,并使用XamlReader将标记实例化为框架对象。
完整的解释相当长,所以我把它发布到我的博客:Highlighting Query Terms in a WPF TextBlock
一个TextBlock
可以在其Run
系列中包含多个Inlines
s。您可以在代码或XAML中构建它:
<TextBlock>
<Run>... these </Run>
<Run FontWeight="Bold">results</Run>
<Run> were found...</Run>
</TextBlock>