7

データ テンプレートを使用して ComboBox 内のいくつかの項目を視覚化します。ItemsSource は ObservableCollection にバインドされています。簡単にするために、ObservableCollection に人を入れたとしましょう。

public class Person {
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

私の DataTemplate は次のようになります。

<DataTemplate TargetType="{x:Type Person}">
  <StackPanel Orientation="Horizontal">
    <TextSearch.Text>
      <MultiBinding StringFormat="{} {0} {1}">
        <Binding Path="FirstName"/>
        <Binding Path="LastName"/>
      </MultiBinding>
    </TextSearch.Text>
    <TextBlock Text="{Binding FirstName}" Margin="2,0" />
    <TextBlock Text="{Binding LastName}"/>
  </StackPanel>
</DataTemplate>

ここで、個人クラスに 3 番目のプロパティを導入せずに、ComboBox で氏名のオートコンプリートを有効にしたいと考えています。したがって、ComboBox で TextSearch.TextPath プロパティを使用したくありませんが、代わりに DataTemplate の各 ComboBoxItem の TextSearch.Text-Property をバインドしたいと考えています。残念ながら、これを行うと (MultiBinding と StringFormat で動作し、Snoop でテストされています)、バインドされた値は StackPanel にのみ登録されますが、Snoop (優れたツール) を使用すると、このスタックパネルがさらにいくつかの ComboBoxItemTemplate のコンテンツとして機能することがわかりました、別の境界線などを配置し、最後に外側の StackPanel の周りに ComboBoxItem タグを配置します。したがって、TextSearch.Text-setting は有効ではありません。これは、作成された ComboBoxItem 内ではなく、その中に設定する必要があるためです。

質問: XAML-Styles と -Control-Templates のみを使用して、この TextSearch.Text-Property を DataTemplate から周囲の ComboBoxItem に伝播するにはどうすればよいですか? このソリューションでは、ComboBox と ComboBoxItem の default-ControlTemplates とカスタム (Item-)DataTemplate を変更できますが、コード ビハインドを使用しないか、少なくともあまり使用しません。たぶん、添付された動作も問題ないでしょう。しかし、TemplateBinding や RelativeSource などを使用せずに機能させる方法があるに違いないと確信しています。リストに Hans Josef と Hans Peter が含まれている場合、'Hans' と入力すると Hans Josef が自動提案されますが、'Hans P' と入力すると Hans Peter が自動提案されます。

解決策はありますか?

4

2 に答える 2

9

簡単な答え: あなたがやりたいことは XAML で直接行うことはできませんが、それを行う方法は他にもあります。

長い答え: ComboBox は、Items または ItemsSource コレクションに格納されているデータ項目で TextSearch.Text プロパティを直接検索します。したがって、データ テンプレートまたはスタイルでプロパティを設定することはできません。それらは、データ項目自体ではなく、データ項目の表示に使用されるオブジェクトに適用されるためです。

特に、TextSearch クラスページの例を見ると、ComboBox.Items コレクションに入る Image オブジェクトに TextSearch.Text プロパティが関連付けられていることがわかります。Person を DependencyObject にすることでプログラムでこれを行うことができますが、そのようなすべてのオブジェクトにプロパティを設定したいとは思いません。

ここにはいくつかのオプションがあります。

Person クラスを変更できる場合は、ToString() メソッドを定義してオートコンプリートするテキストを返すか、Fullname などの任意のプロパティを定義して ComboBox に Textsearch.TextPath を設定できます。例えば:

public class Person
{
     string FirstName { get; set; }
     string LastName {get; set; }
     string FullName { get { return String.Format("{0} {1}", FirstName, LastName); } }
}

<ComboBox TextSearch.TextPath="FullName" ItemsSource="collectionOfPersons"/>

または、Person に触れたくない場合は、これらのプロパティを公開するラッパー クラスを作成できます。

于 2009-11-17T07:33:58.390 に答える
2

パネルを囲むものはデフォルトのコンテナです。TextSearch.Text プロパティをコンテナーに適用する必要があります。これを行うには、次のように ItemContainerStyle を介してプロパティを設定します。

<ComboBox.ItemContainerStyle>
    <Style TargetType="{x:Type ComboBoxItem}">
        <Setter Property="TextSearch.Text">
            <Setter.Value>
                <MultiBinding StringFormat="{} {0} {1}">
                    <Binding Path="FirstName"/>
                    <Binding Path="LastName"/>
                </MultiBinding>
            </Setter.Value>
        </Setter>
    </Style>
</ComboBox.ItemContainerStyle>
于 2009-11-12T17:12:04.903 に答える