3

TextBox と ListBox があります。ユーザーは TextBox から ListBox 要素を検索できます。

ListBox は CollectionViewSource にバインドされています。

CollectionViewSource には、ユーザーが TextBox に入力したテキストに基づいて要素をフィルター処理する Filter イベント ハンドラーがあります。

私の要件は、ListBoxItem 要素の TextBlock 内でユーザーが入力したテキストを強調表示することです。

TextBlock をいくつかの Runs オブジェクトに分割し、強調表示する必要がある Run オブジェクトの Background プロパティを変更することを考えていました。

DataTemplates ではできないと思います。

これを達成する簡単な方法はありますか?

ありがとう!

4

2 に答える 2

9

更新: この件については、このブログ投稿で詳しく説明しました。

これを行う簡単な方法はないと思いますが、この問題に取り組む方法は次のとおりです。

  1. リスト内の項目のビュー モデルを定義します。テキストを公開し、テキストのどの部分を強調表示するかを定義するプロパティを含める必要があります (基本的には開始インデックスと終了インデックス)。
  2. ユーザーが検索ボックスにテキストを入力したら、ビュー モデルを調べて、テキスト内の一致を確認します。一致が見つかった場合は、インデックスを適切に設定します。一致するものが見つからない場合は、インデックスを -1 に戻すか、一致しないことを示す値に戻します。
  3. ビューで、 の をインデックスに設定BackgroundTextBlockます。GradientBrushコンバーターを使用して、インデックスを2 つのインデックス間の明るい黄色 (またはその他)に変換します。

の強調表示された部分の寸法を把握する方法は次のとおりですTextBlock

  1. TextPointerプロパティ経由で取得しTextBlock.ContentStartます。
  2. TextPointer.GetPositionAtOffset(indexOfStart)を使用して呼び出して、選択の先頭に移動しLogicalDirection.Forwardsます。
  3. TextPointer.GetPositionAtOffset(indexOfStart)を使用して呼び出して、選択範囲の最後に移動し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プロパティを活用することをお勧めします。TextBlockDrawingBrushGradientBrushPath

于 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 に答える