3

我有一个文本框和列表框。用户可以从 TextBox 中搜索 ListBox 元素。

ListBox 绑定到 CollectionViewSource。

CollectionViewSource 具有 Filter 事件处理程序,它根据用户输入到 TextBox 的文本过滤元素。

我的要求是在 ListBoxItem 元素的 TextBlock 中突出显示用户输入的文本。

我正在考虑将 TextBlock 分解为几个 Runs 对象并修改需要突出显示的 Run 对象的 Background 属性。

我认为不可能使用 DataTemplates。

有没有简单的方法可以做到这一点?

谢谢你!

4

2 回答 2

9

更新:我在这篇博文中详细阐述了这个主题。

我认为没有任何简单的方法可以做到这一点,但这是我解决这个问题的方法:

  1. 为列表中的项目定义视图模型。它应该包括用于显示文本并定义应该突出显示文本的哪一部分的属性(基本上是开始和结束索引)。
  2. 当用户在搜索框中输入文本时,查看视图模型并检查文本中的匹配项。如果找到匹配项,请适当设置索引。如果未找到匹配项,请将索引设置回 -1 或任何表示不匹配的值。
  3. 在您看来,将sBackgroundTextBlocks 设置为索引。使用转换器将索引转换为GradientBrush两个索引之间的亮黄色(或其他)。

以下是我认为您可以找出突出显示部分的尺寸的方法TextBlock

  1. TextPointer通过TextBlock.ContentStart属性获取。
  2. TextPointer.GetPositionAtOffset(indexOfStart)调用using移动到选择的开头LogicalDirection.Forwards
  3. TextPointer.GetPositionAtOffset(indexOfStart)调用using移动到选择的末尾LogicalDirection.Backwards
  4. 调用TextPointer.GetCharacterRect以获取突出显示内容的边界Rectangle

老实说,我不确定最后一点是否有效。我必须自己尝试一下,我可能会为博客文章这样做。

编辑:刚刚有时间自己尝试一下。它确实有效,尽管我上面的逻辑略有改变。下面是演示的代码。这是一个屏幕截图:

截图 http://img219.imageshack.us/img219/2969/searchx.png

Window1.xaml

<Window x:Class="TextSearch.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1">
    <StackPanel>
        <TextBox x:Name="_searchTextBox"/>
        <Grid>
            <Path Fill="Yellow" Stroke="Black" StrokeThickness="0">
                <Path.Data>
                    <RectangleGeometry x:Name="_rectangleGeometry"/>
                </Path.Data>
            </Path>
            <TextBlock x:Name="_textBlock">Some sample text that you can search through by typing in the above TextBox.</TextBlock>
        </Grid>
    </StackPanel>
</Window>

Window1.xaml.cs

using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;

namespace TextSearch
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
            _searchTextBox.TextChanged += _searchTextBox_TextChanged;
        }

        void _searchTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            var searchText = _searchTextBox.Text;
            var index = _textBlock.Text.IndexOf(searchText);

            if (index == -1)
            {
                _rectangleGeometry.Rect = Rect.Empty;
            }
            else
            {
                var textPointer = _textBlock.ContentStart;
                textPointer = textPointer.GetPositionAtOffset(index + 1, LogicalDirection.Forward);
                var leftRectangle = textPointer.GetCharacterRect(LogicalDirection.Forward);
                textPointer = textPointer.GetPositionAtOffset(searchText.Length, LogicalDirection.Backward);
                var rightRectangle = textPointer.GetCharacterRect(LogicalDirection.Forward);
                _rectangleGeometry.Rect = new Rect(leftRectangle.TopLeft, rightRectangle.BottomRight);
            }
        }
    }
}

我认为代码是不言自明的。显然,您需要将该概念扩展到您的特定场景。您可能更喜欢利用组合的Background属性TextBlocka DrawingBrushorGradientBrush而不是单独的Path.

于 2009-04-28T16:52:29.643 回答
0

在 WPF 列表框中过滤。以下示例代码对我来说很好。

<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
    <TextBox Name="txtSearch" Height="21" Margin="63,12,12,0" VerticalAlignment="Top"></TextBox>
    <ListBox Name="listItems" ItemsSource="{Binding}" Margin="22,0,0,44" Height="179" VerticalAlignment="Bottom" />
</Grid>

VB.net代码

将数据表绑定到您的列表框

Dim _dtable As New DataTable("tblItems") _dtable.Columns.Add("Id", GetType(Integer))
    _dtable.Columns.Add("Name", GetType(String))
    _dtable.Columns.Add("Price", GetType(Double))
    ' Add any initialization after the InitializeComponent() call.
    For i = 100 To 110
        _dtable.Rows.Add(i, "Item " & i, 15.0)
    Next







  Private Sub Window1_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
    listItems.DataContext = _dtable.DefaultView
End Sub
Private Sub txtSearch_TextChanged(ByVal sender As System.Object, ByVal e As System.Windows.Controls.TextChangedEventArgs) Handles txtSearch.TextChanged

_dtable.DefaultView.RowFilter = "名称如 '" & txtSearch.Text & "%'"

End Sub

以上示例代码适用于我

于 2012-06-21T13:59:07.847 回答