2016-01-21 21 views
8

Ho fatto un po 'di programmazione WPF molto tempo fa, ma sto solo tornando a xaml con UWP, ma penso che questo dovrebbe funzionare e non riesco a capire perché. Fondamentalmente voglio usare ItemsControl (perché voglio solo elencare alcuni dati, non voglio selezione) invece di un controllo ListView. Qui sono le mie risorse:ItemsControl e ItemTemplateSelector in Windows 10 UWP app

<Page.Resources> 
    <DataTemplate x:Key="SentMessageDataTemplate"> 
     <TextBlock Text="Sent" /> 
    </DataTemplate> 
    <DataTemplate x:Key="ReceivedMessageDataTemplate"> 
     <TextBlock Text="Recieved" /> 
    </DataTemplate> 
    <services:MessageDataTemplateSelector x:Key="MessageDataTemplateSelector" ReceivedTemplate="{StaticResource ReceivedMessageDataTemplate}" SentTemplate="{StaticResource SentMessageDataTemplate}"></services:MessageDataTemplateSelector> 
</Page.Resources> 

Ecco il mio ItemsControl:

<ItemsControl ItemsSource="{Binding Messages}" ItemTemplateSelector="{StaticResource MessageDataTemplateSelector}" /> 

ecco la mia DataTemplateSelector:

public class MessageDataTemplateSelector : DataTemplateSelector 
{ 
    public DataTemplate SentTemplate 
    { 
     get; 
     set; 
    } 

    public DataTemplate ReceivedTemplate 
    { 
     get; 
     set; 
    } 

    protected override DataTemplate SelectTemplateCore(object item) 
    { 
     var message = item as MessageViewModel; 
     if (message == null) 
     { 
      return this.SentTemplate; 
     } 

     return message.Sent ? this.SentTemplate : this.ReceivedTemplate; 
    } 
} 

Invece di visualizzare uno dei miei modelli solo visualizza il mio nome tipo ViewModel (quindi in pratica ToString).

Tuttavia, se si passa da ItemsControl a ListView, funziona correttamente.

Qualche suggerimento?

+0

Ha avuto lo stesso problema in una delle mie app di recente! Mi chiedo se questo è risolvibile ... – Depechie

risposta

9

Utilizzare questa esclusione invece:

protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) 

Questo è quello che viene chiamato, non l'uno senza l'secondo parametro.

+0

L'ho provato, senza fortuna.ItemsPanelTemplate è uguale al modello predefinito. Funziona bene se imposto un ItemTemplate, semplicemente non gli piace ItemTemplateSelectors. – Cleverguy25

+0

Ho aggiornato la mia risposta. L'override con 1 param non viene mai chiamato (come hai osservato). Ce ne sono 2 disponibili. Difficile. –

0

Forse dovresti usare <TextBlock Text="{Binding Sent}" /> Non legare nulla nel tuo Modello.

+0

Anche se lego qualcosa, non funziona. ListView funziona anche senza legare nulla. Se imposto un punto di interruzione nel mio DataTemplateSelector non viene mai chiamato durante l'esecuzione in un oggetto ItemsControl. Penso che questo sia solo un bug. – Cleverguy25

5

Interessante - ListView e GridView richiamano entrambi il selettore modello; plain ItemsControl o ListBox no.

Override altro metodo SelectTemplateCore nel selettore modello consente, ad es .:

protected override DataTemplate SelectTemplateCore(object item) 
{ 
    var message = item as MessageViewModel; 
    if (message == null) 
    { 
     return SentTemplate; 
    } 

    return message.Sent ? SentTemplate : ReceivedTemplate; 
} 

protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) 
{ 
    return SelectTemplateCore(item); 
} 

Quest'ultimo metodo è chiamato in tutti i casi; il primo non è chiamato per gli articoli ItemsControl. This page fornisce una spiegazione di sorta:

Se il vostro è un ItemsControl.ItemsPanelItemsStackPanel o ItemsWrapGrid, fornire un override per il metodo SelectTemplateCore(Object). Se lo ItemsPanel è un pannello diverso, ad esempio VirtualizingStackPanel o WrapGrid, fornire un override per il metodo SelectTemplateCore(Object, DependencyObject).

+0

Kory ti ha battuto per pochi minuti, ma il tuo link alla documentazione è stato utile. – Cleverguy25

0

Ecco cosa dice la documentazione:

Osservazioni

Se il vostro è un ItemsControl.ItemsPanel ItemsStackPanel o ItemsWrapGrid, fornire un override per il metodo SelectTemplateCore (Object). Se ItemsPanel è un pannello diverso, come VirtualizingStackPanel o WrapGrid, fornire un override per il metodo SelectTemplateCore (Object, DependencyObject).

Problemi correlati