Cannot keep ListView ordered/sorted when navigating away and back

Hello!

I'm learning the ListView control and sorting data it shows, but i can't seem to fix a scenario.
I am using Visual Studio 2017 Community.

I am trying to have a list always ordered by this criteria:

  • column create date (DateTime.Now)
  • order descending

The following 3 scenarios must work with the same order criteria applied, but i can't seem to make it work for the 3rd one.
1) (working) When i open the app the 1st time (done with sorting in overriden Init method
2) (working) When i add items in the list (enter/done/verify on a specific Entry control adds to my ListView an item)
3) (not working) When, while the app is running , i navigate to another Page and back to the one that keeps this ListView

1) was solved with overriding Init method of the viewModel (which keeps the ObservableCollection prop)
2) was solved by using ObservableCollection.Insert(,item) instead of ObservableCollection.Add()
3) In the view, i tried overriding OnAppearing

In XAML:
<ListView
x:Name="ItemListView"
ItemsSource="{Binding Items}"
CachingStrategy="RecycleElement"

            HorizontalOptions="CenterAndExpand"
            VerticalOptions="CenterAndExpand"

            >
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout
                            Spacing="10"
                            Orientation="Horizontal"
                            >
                            <StackLayout>
                                <Label
                                    Text="{Binding Code}"
                                />

                                <Label
                                    Text="{Binding Description}"
                                />
                            </StackLayout>

                            <Label
                                Text="{Binding Number}"
                                FontAttributes="Bold"
                                VerticalOptions="Center"
                            />
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

In code-behind of View:

protected override async void OnAppearing()
{
base.OnAppearing();
await _itemViewModel.SaveItem(); //does some SQLite work related to Items
_itemPageViewModel.SortItems();
ItemListView.ItemsSource = _itemViewModel.Items;
}

In View-Model:
internal void SortItems()
{
Items.OrderByDescending(x => x.CreateDate);
}

However, when i repeatedly exit the Page and reenter, the items are unsorted.

Best Answer

  • AlexParaschivAlexParaschiv ✭✭
    Accepted Answer

    @deczaloth I agree, it was interrupting binding, however it was not the biggest problem.
    I removed sorting and reassigning ItemsSource in OnAppearing.

    I learned that after OnAppearing(), due to how i manage pages and navigation, Init was called all the time i reentered it.
    My actual problem ended up being populating the list, as i was LINQ-ing data from a local SQLite DB and obtaining one of the fields in my object initializer with an await.

    I have a page which contains a list of headers and when i click it, it opens another page where this ListView is used to show the details.
    The ObservableCollection for details did not hold all the data because i wanted it to be as lightweight as possible.
    (due to possibility of having the list contain thousands of items, populating it with a long description for the item felt like heavy memory loading, which i wanted to avoid)
    The following code was my actual issue:

    ItemList.ForEach(
    async x=> Items.Add(new Item()
    {
    ID = x.ID,
    Code = x.Code,
    Description = (await _sqLiteHandler.GetItemsAsync(x.ID,x.Code)).Description
    }
    ));

    I ended up populating the list separately from completing Description for each item in the list.

Answers

  • deczalothdeczaloth DEMember ✭✭✭

    Hi @AlexParaschiv,

    I am not sure what is exactly wrong in your case, but at least i can see that with
    ItemListView.ItemsSource = _itemViewModel.Items;
    in your code behind you are killing the nice binding that you set in the XAML.
    Try instead binding also there (i wrote the following without testing, but to serve as an idea):
    ItemListView.SetBinding(ListView.ItemsSourceProperty, "Items");

  • AlexParaschivAlexParaschiv Member ✭✭
    Accepted Answer

    @deczaloth I agree, it was interrupting binding, however it was not the biggest problem.
    I removed sorting and reassigning ItemsSource in OnAppearing.

    I learned that after OnAppearing(), due to how i manage pages and navigation, Init was called all the time i reentered it.
    My actual problem ended up being populating the list, as i was LINQ-ing data from a local SQLite DB and obtaining one of the fields in my object initializer with an await.

    I have a page which contains a list of headers and when i click it, it opens another page where this ListView is used to show the details.
    The ObservableCollection for details did not hold all the data because i wanted it to be as lightweight as possible.
    (due to possibility of having the list contain thousands of items, populating it with a long description for the item felt like heavy memory loading, which i wanted to avoid)
    The following code was my actual issue:

    ItemList.ForEach(
    async x=> Items.Add(new Item()
    {
    ID = x.ID,
    Code = x.Code,
    Description = (await _sqLiteHandler.GetItemsAsync(x.ID,x.Code)).Description
    }
    ));

    I ended up populating the list separately from completing Description for each item in the list.

Sign In or Register to comment.