2010-10-01 8 views
7

Sono in grado di utilizzare un ItemTemplate all'interno di ItemsControl per eseguire il rendering di elementi in un formato specifico. Tuttavia, se uno degli elementi all'interno di ItemsControl sembra essere, ad esempio, un controllo TextBox, viene eseguito il rendering di TextBox anziché un'istanza di ItemsTemplate. Da quello che posso dire, questo è vero per qualsiasi FrameworkElement. Questo comportamento è previsto per un oggetto ItemsControl o sto facendo qualcosa in modo errato?Perché ItemsControl non utilizza My ItemTemplate?

Un esempio:

<ItemsControl> 
    <ItemsControl.ItemTemplate> 
    <DataTemplate> 
     <Grid Margin="5"> 
     <Rectangle Fill="Blue" Height="20" Width="20" /> 
     </Grid> 
    </DataTemplate> 
    </ItemsControl.ItemTemplate> 
    <ItemsControl.Items> 
    <sys:Object /> 
    <TextBox /> 
    <sys:Object /> 
    <Rectangle Fill="Red" Height="20" Width="20" /> 
    </ItemsControl.Items> 
</ItemsControl> 

mi aspettavo questo per visualizzare quattro rettangoli blu. Ho pensato che ogni volta che un ItemTemplate è stato definito ogni elemento della collezione è reso come un'istanza del modello. Tuttavia, in questo caso viene visualizzato il seguente: un rettangolo blu seguito da un riquadro di testo seguito da un rettangolo blu seguito da un rettangolo rosso.

+0

Sto indovinando che questo è inteso comportamento, ed è destinato a consentire agli sviluppatori la possibilità di aggiungere speciali controlli di utilizzo monouso. Ad esempio, potrei usare questo per aggiungere un pulsante a un ComboBox che cancella la selezione, oppure potrei mettere un TextBox in un ListBox che filtra la raccolta specificata da ItemsSource. Mi piacerebbe sapere che qualcuno ha una risposta ufficiale per questo comportamento perché l'ho trovato contro-intuitivo all'uso di un ItemTemplate. – Drew

+0

Ottima domanda e ottima risposta di Anthony, grazie ragazzi. – Golvellius

risposta

12

Il ItemsControl ha un membro protetto IsItemItsOwnContainerOverride che è passato un oggetto della collezione oggetti e restituisce true se l'oggetto può essere aggiunto direttamente al pannello articoli senza un contenitore generato (e quindi essere templato).

L'implementazione di base restituisce true per qualsiasi oggetto che deriva da UIElement.

Per ottenere il comportamento che ci si aspetterebbe sarebbe necessario ereditare da ItemsControl e sovrascrivere questo metodo e farlo restituire sempre false. Purtroppo non è la fine della questione. L'implementazione predefinita di PrepareContainerForItemOverride continua a non assegnare il ItemTemplate al contenitore se l'articolo è un UIElement quindi è necessario eseguire l'override di questo metodo così: -

protected override bool IsItemItsOwnContainerOverride(object item) 
    { 
     return false; 
    } 


    protected override void PrepareContainerForItemOverride(DependencyObject element, object item) 
    { 
     base.PrepareContainerForItemOverride(element, item); 
     ((ContentPresenter)element).ContentTemplate = ItemTemplate; 
    } 
+1

A partire dal 2015, potrebbero aver risolto la seconda parte. Con WPF in .NET 4.5.1, se restituisco 'false' per' IsItemItsOwnContainerOverride, 'allora il modello sembra essere impostato sul contenitore dell'elemento. –

2

Sto solo speculando qui, ma scommetto che è un comportamento che vive all'interno dello ItemContainerGenerator. Scommetterei che lo ItemContainerGenerator guardi un oggetto, e se si tratta di un UIElement dice, "cool, il contenitore degli articoli è stato generato, lo restituisco" e se non lo è, dice: "È meglio che generi un contenitore per questo articolo. Dov'è il numero DataTemplate? "

Problemi correlati