Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 767
zrkl Avatar asked Oct 30 '13 18:10

zrkl


2 Answers

I haven't got the solution but maybe a clue for someone who will solve the problem.
I think the problem is with LongListSelector.UpdateLayout() method - when it's fired for the first time there are no items to which LLS was bound - OnChangeMethod is called that many times as the Itemsource.Count. But when we leave the page and go back - LLS is Updated and method is called ommiting the middle element.
It means it works for even number of items - OnChangeMethod is called correct number of times, But for odd number of items - it's called numer of items - 1.
The second thing is why it's called at all - when there are no changes.

I also add a code to work on which (very simple).

like image 188
Romasz Avatar answered Oct 20 '22 09:10

Romasz


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?

like image 24
Ebsan Avatar answered Oct 20 '22 07:10

Ebsan