7

私は非常に単純な例を持っています:データを持つ辞書を含む単一のフォームを持つWPFフォームアプリケーション:

Dim dict As New Collections.Generic.Dictionary(Of String, String)

Private Sub MainWindow_Loaded() Handles Me.Loaded
    dict.Add("One", "1")
    dict.Add("Two", "2")
    dict.Add("Three", "3")

    lst1.ItemsSource = dict
End Sub

フォームには、項目ソースとして「dict」を使用する ListBox (「lst1」という名前) があります。

<ListBox x:Name="lst1">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Label Content="{Binding Value}" 
                   TextSearch.Text="{Binding Path=Key, Mode=OneWay}" />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

また、手動で値が事前に入力された、バインドされていない ListBox が 1 つあります。

<ListBox>
    <Label TextSearch.Text="One" Content="1" />
    <Label TextSearch.Text="Two" Content="2" />
    <Label TextSearch.Text="Three" Content="3" />
</ListBox>

したがって、アプリを起動すると、次のようになります。

アプリケーションのウィンドウ

質問:

「one」、「two」、または「three」と入力してキーボードでアイテムをナビゲートしようとすると、バインドされていないリスト ボックスでのみ成功します。バインドされたリスト ボックスが失敗します。

いくつかの注意事項: 1.) バインドされたリスト ボックスで「[」を押すと、フォーカスが項目から項目へ循環的に変化します: 1 から 2 へ、2 から 3 へ、3 から 1 へ、1 から 2 へ再び移動します。など 2.) Snoop でアプリを確認しました。バインドされたリスト ボックスとバインドされていないリスト ボックスの違いを 1 つ見つけました。どちらのリスト ボックスにも、Label コントロール (ItemsPresenter 内) に TextSearch.Text プロパティが設定されています。ただし、バインドされていない場合: TextSearch.Text プロパティの「値のソース」は「ローカル」です。バインドされたケースの場合: 「値のソース」は「ParentTemplate」です。

PS(およびNB) リストボックスでTextSearch.TextPathを使用できることはわかっていますが、これは私が必要とするものではありません:)また、ListViewItemのTextSearch.Textプロパティを(スタイルを使用して)設定しても役に立ちません。

4

2 に答える 2

12

TextSearch が ItemsControl でどのように機能するかを正確に説明することから始めましょう。

TextSearch の実装は、ItemsSourceプロパティの実際のデータ項目を列挙し、それらを直接Text調べて依存関係プロパティを読み取ります。ListBoxItem例のように sを入れると、実際のアイテムは依存関係プロパティが「アタッチ」されたListBoxItemインスタンスであるため、機能します。Textにバインドすると、 sではないインスタンスをDictionary<>直接見ているため、プロパティを持つことができない/持たない. これが、経由でプロパティを設定しても効果がない理由でもあります。 はデータがビジュアル ツリーでどのように表示されるかを記述していますが、KeyValuePair<>DependencyObjectTextSearch.TextTextSearch.TextListBoxItemItemContainerStyleItemContainerStyleTextSearchエンジンは生データ ソースのみを考慮します。UI でそのデータをどのようにスタイルしたかは関係ありません。そのため、 a を変更してDataTemplateも には何も起こりませんTextSearch

1 つの代替方法は、検索可能にしたい値に基づいてDependencyObject、添付プロパティを設定した場所から継承するビュー モデル クラスを作成することです。TextSearch.Textこれがどのように機能するかを示すサンプル コードを次に示します。

private sealed class MyListBoxItem : DependencyObject
{
    public static readonly DependencyProperty KeyProperty = DependencyProperty.Register("Key", typeof(string), typeof(MyListBoxItem), new FrameworkPropertyMetadata(string.Empty));
    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(string), typeof(MyListBoxItem), new FrameworkPropertyMetadata(string.Empty));

    public string Key
    {
        get
        {
            return (string)GetValue(KeyProperty);
        }
        set
        {
            SetValue(KeyProperty, value);
            SetValue(TextSearch.TextProperty, value);
        }
    }

    public string Value
    {
        get
        {
            return (string)GetValue(ValueProperty);
        }
        set
        {
            SetValue(ValueProperty, value);
        }
    }
}

// Assign a list of these as the list box's ItemsSource
this.listBox.ItemsSource = new List<MyListBoxItem>
{
    new MyListBoxItem { Key = "One", Value = "1" },
    new MyListBoxItem { Key = "Two", Value = "2" },
    new MyListBoxItem { Key = "Three", Value = "3" }
};

ListBox の定義は次のようになります。

<ListBox Name="listBox">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Value}" />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

他の代替手段では を使用する必要がありますがTextSearch.TextPath、それに対して完全に反対しているようです。の変更が機能しないことを受け入れるようになった場合DataTemplate、推奨する解決策は、検索に使用するプロパティを持つ POCO ビューモデルを作成し、それを に指定することTextSearch.TextPathです。これは、あなたがやっていることを達成するための最も軽量で非ハックな方法です。

于 2012-04-16T04:47:20.027 に答える
6

ListBoxItem考えられる解決策は、設定されていないTextSearch.Textか設定されている場合のデータ項目で .ToString() を使用する TextSearch のフォールバック動作を使用することですTextSearch.TextPath

たとえば、これにより、TextSearch.Text または .TextPath を指定せずに検索できます。

<Page.DataContext>
    <Samples:TextSearchViewModel/>
</Page.DataContext>

<Grid>
    <ListBox ItemsSource="{Binding Items}" 
             IsTextSearchCaseSensitive="False" 
             IsTextSearchEnabled="True">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Label Content="{Binding Value}" />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Grid>

public class TextSearchItem
{
    public int Value { get; set; }
    public string SearchText { get; set; }

    public override string ToString()
    {
        return SearchText;
    }
}

public class TextSearchViewModel
{
    public TextSearchViewModel()
    {
        Items = new List<TextSearchItem>
                    {
                        new TextSearchItem{ Value = 1, SearchText = "One"},
                        new TextSearchItem{ Value = 2, SearchText = "Two"},
                        new TextSearchItem{ Value = 3, SearchText = "Three"},
                        new TextSearchItem{ Value = 4, SearchText = "Four"},
                    };
    }

    public IEnumerable<TextSearchItem> Items { get; set; }
}
于 2012-04-18T11:33:20.130 に答える