Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ItemsControl and ItemTemplateSelector in Windows 10 UWP app

I did a little WPF programming a long time ago, but I am just returning to xaml with UWP, but I think this should work and cannot figure out why. Basically I want to use an ItemsControl (because I just want to list some data, I don't want selection) instead of a ListView control. Here are my resources:

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

Here is my ItemsControl:

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

Here is my 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;
    }
}

Instead of displaying either of my templates it just displays my ViewModel type name (so basically ToString).

However if I switch it from ItemsControl to ListView, it works fine.

Any suggestions?

like image 817
Cleverguy25 Avatar asked Jan 21 '16 06:01

Cleverguy25


2 Answers

Use this override instead:

protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)

This is the one that gets called, not the one without the 2nd parameter.

like image 175
Kory Gill Avatar answered Sep 21 '22 19:09

Kory Gill


Interesting -- ListView and GridView both invoke the template selector; plain ItemsControl or ListBox do not.

Overriding the other SelectTemplateCore method in the template selector helps, e.g.:

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);
}

The latter method is called in all cases; the first isn't called for ItemsControl items. This page provides an explanation of sorts:

If your ItemsControl.ItemsPanel is an ItemsStackPanel or ItemsWrapGrid, provide an override for the SelectTemplateCore(Object) method. If the ItemsPanel is a different panel, such as VirtualizingStackPanel or WrapGrid, provide an override for the SelectTemplateCore(Object, DependencyObject) method.

like image 40
Petter Hesselberg Avatar answered Sep 20 '22 19:09

Petter Hesselberg