Search code examples
c#windows-phone-8windows-phonelonglistselectordatatemplateselector

LongListSelector and DataTemplateSelector


I'm using the LongListSelector to realize List or Grid display for my items. For this, I created a DataTemplateSelector and I change the LayoutMode property at runtime. This is working but there seems to be an issue with the DataTemplateSelector. If I initially launch the page, the DataTemplateSelector is called three times for my three items. When I navigate to another page (settings page to change the LayoutMode) and then back, the DataTemplateSelector is just called two items but there are still three items.

DataTemplateSelector:

public abstract class DataTemplateSelector : ContentControl
{
    public virtual DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        return null;
    }

    protected override void OnContentChanged(object oldContent, object newContent)
    {
        base.OnContentChanged(oldContent, newContent);

        ContentTemplate = SelectTemplate(newContent, this);
    }
}

ItemViewModeTemplateSelector:

public class ItemViewModeTemplateSelector: DataTemplateSelector
{
    public DataTemplate ListViewModeTemplate
    {
        get;
        set;
    }

    public DataTemplate GridViewModeTemplate
    {
        get;
        set;
    }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        ViewMode viewMode = ViewMode.Grid;

        // Get ViewMode from IsolatedStorageSettings...

        switch (viewMode)
        {
            case ViewMode.Grid:
                return GridViewModeTemplate;

            case ViewMode.List:
                return ListViewModeTemplate;
        }

        return base.SelectTemplate(item, container);
    }
}

MainPage.xaml:

<phone:LongListSelector x:Name="ItemLongListSelector" ItemsSource="{Binding Items}" LayoutMode="Grid" GridCellSize="222,222">
    <phone:LongListSelector.ItemTemplate>
        <DataTemplate>
            <common:ItemViewModeTemplateSelector Content="{Binding}" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
                <common:ItemViewModeTemplateSelector.GridViewModeTemplate>
                    <DataTemplate>
                        <StackPanel Margin="12,12,0,0" Background="{Binding Color, Converter={StaticResource ColorToBrushConverter}}">
                            <!-- Content -->
                        </StackPanel>
                    </DataTemplate>
                </common:ItemViewModeTemplateSelector.GridViewModeTemplate>

                <common:ItemViewModeTemplateSelector.ListViewModeTemplate>
                    <DataTemplate>
                        <StackPanel>
                            <!-- Content -->
                        </StackPanel>
                    </DataTemplate>
                </common:ItemViewModeTemplateSelector.ListViewModeTemplate>
            </common:ItemViewModeTemplateSelector>
        </DataTemplate>
    </phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>

This is the display when I initially launch the page:

Then I navigate to another page and then back:

EDIT: I prepared a sample project for this issue. It should run without problems.

Project: http://sdrv.ms/1cAbVxE


Solution

  • I've done something similar with my app, but allowed the user to choose the LayoutMode of LLS using an Appbar button. I basically change the LongListSelector.LayoutMode and then it's ItemTemplate in code and the LLS automatically refreshes itself. I'm not sure if this will help, but here's my code.

    private void layoutModeButton_Click(object sender, EventArgs e)
        {
            ApplicationBarIconButton layoutModeButton = (ApplicationBarIconButton)ApplicationBar.Buttons[0];
    
            if (MainLongListSelector.LayoutMode == LongListSelectorLayoutMode.Grid)
            {
                MainLongListSelector.LayoutMode = LongListSelectorLayoutMode.List;
                MainLongListSelector.ItemTemplate = this.Resources["ListListLayout"] as DataTemplate;
                layoutModeButton.IconUri = _gridButtonUri;
                layoutModeButton.Text = "grid";
            }
            else
            {
                MainLongListSelector.LayoutMode = LongListSelectorLayoutMode.Grid;
                MainLongListSelector.ItemTemplate = this.Resources["GridListLayout"] as DataTemplate;
                layoutModeButton.IconUri = _listButtonUri;
                layoutModeButton.Text = "list";
            }
        }
    

    You might have figured out the answer already, but just to add to the conversation: this gives me really good performance for a fairly large amount of data. Maybe you can do something similar when navigating back to the page after changing the layout in settings?