2009-07-10 8 views
5

Uso un datatemplate per visualizzare alcuni elementi in un ComboBox, l'ItemSource è associato a ObservableCollection. Per farla semplice, diciamo che ho messo persone in ObservableCollection:Impostare TextSearch.Text per WPF-ComboBoxItem tramite DataTemplate

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

mio DataTemplate assomiglia a questo:

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

Ora voglio per consentire il completamento automatico per i nomi completi nel ComboBox senza introdurre un terza proprietà sulla mia classe di persona. Quindi non voglio usare TextSearch.TextPath Property sul ComboBox, ma preferirei associare la proprietà TextSearch.Text di ogni ComboBoxItem nel DataTemplate. Sfortunatamente, quando lo faccio (che funziona con un MultiBinding e StringFormat, testato con Snoop), il valore associato è registrato solo per il mio StackPanel, ma usando Snoop (ottimo strumento) ho scoperto che questo stackpanel serve come contenuto per qualche altro ComboBoxItemTemplate, che mette un altro bordo ecc. E infine un tag ComboBoxItem attorno al mio StackPanel esterno. Pertanto, l'impostazione TextSearch.Text non è efficace, perché deve essere impostata nel ComboBoxItem creato e non da qualche parte all'interno.

domanda ora: Come posso propagare a questo TextSearch.Text-Proprietà dal mio DataTemplate alle circostanti ComboBoxItem utilizzando XAML-Stili e solo -Control-Modelli? La soluzione può modificare i ControlTemplates predefiniti di ComboBox e ComboBoxItem e il mio DataTemplate personalizzato (Item-), ma non utilizzare alcun Code-Behind, o almeno non troppo. Forse un comportamento attaccato andrebbe bene, anche. Ma sono quasi sicuro che ci deve essere un modo per farlo funzionare senza, TemplateBinding o RelativeSource-stuff ... E ovviamente la soluzione deve fare in modo che la mia selezione da tastiera e la gestione del testo funzionino, per esempio. quando la lista contiene Hans Josef e Hans Peter, quindi entrare in "Hans" dovrebbe autosuggest Hans Josef, mentre entrare "Hans P" abbastanza rapidamente dovrebbe autosuggest Hans Peter.

Qualche soluzione?

+0

Almeno ora mi sento abbastanza fiducioso, che il compito non è davvero troppo facile. O il lungo testo fa semplicemente scappare la gente in preda al panico ... –

+0

Sono vicino a rinunciare. Sono riuscito a far sì che ComboBoxItem abbia la corretta proprietà TextSearch.Text impostandola in ComboBox.ItemContainerStyle (anziché in ItemTemplate, come facevo prima). Ora sembra molto bello nell'albero visivo (Snoop di nuovo), ma sfortunatamente non ha alcun effetto. Non è stata effettuata alcuna selezione dopo aver digitato "Hans" o qualsiasi altra cosa. –

risposta

1

Quella roba che circonda il pannello è il contenitore predefinito. Devi applicare la proprietà TextSearch.Text al contenitore. Si dovrebbe essere in grado di fare questo impostando la proprietà attraverso l'ItemContainerStyle in questo modo:

<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

Suoni perfettamente ragionevoli, ma sfortunatamente non funziona. La selezione della tastiera non si comporta come desiderato, probabilmente l'input è ancora paragonato al valore ToString delle persone, il testo text.text non ha alcun effetto. Suppongo che il collegamento funzioni, ma il ComboBox lo ignora. –

+0

non funziona per me non puoi indirizzare questo TextSearch.Text dallo stile – Hisham

8

Risposta breve: che cosa si vuole fare non può essere fatto direttamente in XAML, ma ci sono altri modi per farlo.

Risposta lunga: il ComboBox cerca la proprietà TextSearch.Text direttamente sugli elementi di dati memorizzati nella raccolta Items o ItemsSource. Pertanto, non è possibile impostare la proprietà nel modello di dati o nello stile perché si applicano agli oggetti utilizzati per visualizzare gli elementi di dati e non agli stessi dati.

In particolare, se si guardano gli esempi nella pagina TextSearch class, si vedrà che allega la proprietà TextSearch.Text agli oggetti Image che entrano nella raccolta ComboBox.Items. Potresti farlo nel tuo programma rendendo Person a DependencyObject, ma non penso che tu voglia impostare la proprietà su ogni singolo oggetto come quello.

Sono disponibili diverse opzioni qui:

Se è possibile modificare la classe persona, è possibile definire il metodo ToString() per restituire il testo da Completamento automatico o definire una proprietà arbitraria come Fullname e impostare Textsearch.TextPath sul ComboBox.Per esempio:

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

e

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

Altenatively, se non si vuole toccare una persona, è possibile creare una classe wrapper che espone queste proprietà.

+2

Ho paura che tu abbia ragione. Ormai non esiste una soluzione funzionante senza aggiungere una proprietà aggiuntiva alla classe o anche un nuovo pacchetto di classe ed estendendo quello vecchio. Come la domanda dice che queste possibilità sono conosciute ma non volute, non posso contrassegnarlo come _la_ risposta - a meno che forse se estendi la tua risposta breve con qualche prova o spiegazione, perché sia ​​impossibile. –