Forum Xamarin.Forms
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

Could I sort a ListView or a ListView.ItemTemplate by a value in a specific?

victcdvavictcdva Member ✭✭
edited March 27 in Xamarin.Forms

Hi, I trying to sort or order a ListView by a value in a specific, for example by date but I haven't anything like that,
My ListView:

<ListView  x:Name="ItemsListView" RefreshCommand="{Binding LoadItemsCommand}" IsRefreshing="{Binding IsBusy, Mode=OneWay}" SeparatorVisibility="None" Style="{ StaticResource ResponsiveLandscapeMarginStyle }" ItemsSource="{ Binding Messages }">
        <ListView.RowHeight>
            <OnIdiom x:TypeArguments="x:Int32" Phone="120" Tablet="160" />
        </ListView.RowHeight>

    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>

                <local:DataItemTemplate />

            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Is there a way to sort by date or by any value, to display the values in the ListView?

Best Answer

  • victcdvavictcdva Member ✭✭
    edited March 30 Accepted Answer

    @galactose I tried this:

    async Task ExecuteLoadItemsCommand()
    {
    
        if (IsBusy)
            return;
        IsBusy = true;
    
        try
        {
            var serviceStore = new ServiceStoreAPI();
            await serviceStore.GetItemsAsync(ServicesKey.Event,true);
            await serviceStore.GetItemsAsync(ServicesKey.EmployeeServicesRequests, true);
            await serviceStore.GetItemsAsync(ServicesKey.Raffle, true);
            new EmployeeServicesRequestsViewModel().LoadItemsCommand.Execute(null);
            new RaffleViewModel().LoadItemsCommand.Execute(null);
            Messages.Clear();
            var items = await NoticeStore.GetItemsAsync(true);
    
        //THIS IS THE CHANGE
            foreach (var item in items.OrderBy(o => o.Date))
                Messages.Add(item);
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex);
        }
        finally
        {
            IsBusy = false;
        }
    }
    

Answers

  • galactosegalactose Member ✭✭
    Hi,

    You have to set it progammatically in your ViewModel (or in your binding source):

    ```csharp
    private ObservableCollection<Message> _messages;
    public ObservableCollection<Message> Messages
    {
    get => _messages.OrderBy(m => m.Date);
    set { _messages = value; OnPropertyChanged(); }
    }
    ```

    It is not possible to do it in your XAML file, or you will need a converter (so more complex than in code-behind).
  • victcdvavictcdva Member ✭✭
    edited March 30

    This is my ViewModel:

     public class NoticeViewModel : BaseViewModel
     {
        async Task ExecuteLoadItemsCommand()
        {
    
            if (IsBusy)
                return;
            IsBusy = true;
    
            try
            {
                var serviceStore = new ServiceStoreAPI();
                await serviceStore.GetItemsAsync(ServicesKey.Event,true);
                await serviceStore.GetItemsAsync(ServicesKey.EmployeeServicesRequests, true);
                await serviceStore.GetItemsAsync(ServicesKey.Raffle, true);
                new EmployeeServicesRequestsViewModel().LoadItemsCommand.Execute(null);
                new RaffleViewModel().LoadItemsCommand.Execute(null);
                Messages.Clear();
                var items = await NoticeStore.GetItemsAsync(true);
    
                foreach (var item in items)
                    Messages.Add(item);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
            }
            finally
            {
                IsBusy = false;
            }
        }
    }
    

    @galactose but I don't know how to applicate it, is just that?

    get => _messages.OrderBy(m => m.Date);
    set { _messages = value; OnPropertyChanged();
    
  • victcdvavictcdva Member ✭✭
    edited March 30 Accepted Answer

    @galactose I tried this:

    async Task ExecuteLoadItemsCommand()
    {
    
        if (IsBusy)
            return;
        IsBusy = true;
    
        try
        {
            var serviceStore = new ServiceStoreAPI();
            await serviceStore.GetItemsAsync(ServicesKey.Event,true);
            await serviceStore.GetItemsAsync(ServicesKey.EmployeeServicesRequests, true);
            await serviceStore.GetItemsAsync(ServicesKey.Raffle, true);
            new EmployeeServicesRequestsViewModel().LoadItemsCommand.Execute(null);
            new RaffleViewModel().LoadItemsCommand.Execute(null);
            Messages.Clear();
            var items = await NoticeStore.GetItemsAsync(true);
    
        //THIS IS THE CHANGE
            foreach (var item in items.OrderBy(o => o.Date))
                Messages.Add(item);
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex);
        }
        finally
        {
            IsBusy = false;
        }
    }
    
  • galactosegalactose Member ✭✭
    Yes ! This should work.
    I did not try but I think OrderBy() in the getter would work too.

    Note that if you need to update (Add) your collection, you have to write a custom AddSorted() method for ObservableCollection, because Add() will raise a CollectionChanged event but it will not "read" the getter again so the new item will appear at the last position.
Sign In or Register to comment.