2009-07-10 8 views
5

J'utilise un datatemplate pour visualiser certains éléments dans un ComboBox, le ItemsSource est lié à un ObservableCollection. Pour simplifier, disons que je mets les personnes dans le ObservableCollection:Définir TextSearch.Text pour WPF-ComboBoxItem via DataTemplate

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

Mon DataTemplate ressemble à ceci:

<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> 

Maintenant, je veux permettre autocomplétion des noms complets dans la zone de liste déroulante sans introduire une troisième propriété sur ma classe de personne. Par conséquent, je ne souhaite pas utiliser la propriété TextSearch.TextPath dans la zone de liste déroulante, mais je souhaite lier la propriété TextSearch.Text de chaque objet ComboBoxItem dans le DataTemplate. Malheureusement, quand je fais cela (qui fonctionne avec MultiBinding et StringFormat, testé avec Snoop), la valeur liée est enregistrée pour mon StackPanel seulement, mais en utilisant Snoop (excellent outil), j'ai trouvé que cette pile sert de contenu pour ComboBoxItemTemplate, qui place une autre bordure etc. et enfin une balise ComboBoxItem autour de mon StackPanel externe. Par conséquent, le paramètre TextSearch.Text n'est pas efficace, car il doit être défini dans le ComboBoxItem créé, et non quelque part à l'intérieur. Comment puis-je propager cette TextSearch.Text-Property de mon DataTemplate au ComboBoxItem environnant en utilisant XAML-Styles et -Control-Templates uniquement? La solution peut modifier les ControlTemplates par défaut de ComboBox et ComboBoxItem et mon DataTemplate personnalisé (Item-), mais ne pas utiliser de Code-Behind, ou du moins pas trop. Peut-être qu'un comportement attaché serait bien aussi. Mais je suis presque sûr qu'il doit y avoir un moyen de le faire fonctionner sans, TemplateBinding ou RelativeSource-stuff ... Et bien sûr, la solution doit faire en sorte que ma sélection au clavier et la complétion de texte fonctionnent. Quand la liste contient Hans Josef et Hans Peter, alors entrer 'Hans' devrait autosugguer Hans Josef, alors qu'entrer 'Hans P' assez rapidement devrait autosuggest Hans Peter.

Des solutions?

+0

Au moins maintenant je me sens assez confiant, que la tâche n'est en effet pas trop facile. Ou le texte long fait juste fuir les gens ... –

+0

Je suis sur le point de l'abandonner. J'ai réussi à obtenir le ComboBoxItem pour porter la TextSearch.Text-propriété correcte en le définissant dans le ComboBox.ItemContainerStyle (au lieu du ItemTemplate, comme je l'ai fait auparavant). Maintenant, il semble assez bien dans l'arbre visuel (Snoop à nouveau), mais malheureusement, il n'a aucun effet. Il n'y a pas de sélection après avoir tapé "Hans" ou autre chose. –

Répondre

1

Ce truc entourant votre panneau est le conteneur par défaut. Vous devez appliquer la propriété TextSearch.Text au conteneur. Vous devriez être en mesure de le faire en définissant la propriété via le ItemContainerStyle comme ceci:

<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> 
+0

Semble parfaitement raisonnable, mais ne fonctionne malheureusement pas. La sélection du clavier ne se comporte pas comme souhaité, probablement l'entrée est toujours comparée à la valeur ToString des personnes, le textsearch.text n'a aucun effet du tout. Je suppose que la liaison fonctionne, mais la ComboBox l'ignore. –

+0

ne fonctionne pas pour moi, vous ne pouvez pas cibler cette TextSearch.Text du style – Hisham

8

Réponse courte: ce que vous voulez faire ne peut pas être fait directement dans XAML, mais il y a d'autres façons de le faire. Réponse longue: le contrôle ComboBox recherche directement la propriété TextSearch.Text sur les éléments de données stockés dans la collection Items ou ItemsSource. Par conséquent, vous ne pouvez pas définir la propriété dans le modèle de données ou le style car ils s'appliquent aux objets utilisés pour afficher les éléments de données, et non aux éléments de données eux-mêmes.

En particulier, si vous regardez les exemples sur la page TextSearch class, vous verrez qu'ils attachent la propriété TextSearch.Text aux objets Image qui vont dans la collection ComboBox.Items. Vous pouvez le faire dans votre programme en faisant de Person un DependencyObject, mais je ne pense pas que vous voulez définir la propriété sur chaque objet comme ça.

Vous avez plusieurs options:

Si vous pouvez modifier la classe Person, vous pouvez définir la méthode ToString() pour renvoyer le texte à définir ou saisie semi-automatique une propriété arbitraire comme Textsearch.TextPath et mettre Fullname sur le ComboBox.Par exemple:

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

et

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

Altenatively, si vous ne voulez pas toucher personne, vous pouvez créer une classe wrapper qui expose ces propriétés.

+2

Je crains que vous avez raison. A ce jour, il n'y a pas de solution de travail sans ajouter une propriété supplémentaire à la classe ou même une nouvelle classe enveloppant et prolongeant l'ancienne. Comme la question indique que ces possibilités sont connues mais ne sont pas voulues, je ne peux pas marquer cela comme _le_ réponse - sauf peut-être si vous étirez votre réponse courte par une preuve ou une explication, pourquoi c'est impossible. –