1

After searching every forum online I decided to post my own question: My listview data is shown correctly in IOS but not in Android. I'm binding to a property in my view model and that looks correct but I can't figure out what I'm missing (I'm trying to get a list of orders to populate my listview). Any help is appreciated!

Also, I'm using a tabbed page layout. Not sure if that makes a difference or not.

//View model
public ObservableCollection<GroupedOrderModel> ListOfOrdersGrouped
{

            get { return listOfOrdersGrouped; }
            set {
                listOfOrdersGrouped = value;
                NotifyPropertyChanged("listOfOrdersGrouped");
            }
        }

    public class OrderList : List<OrderStatusInfo>
    {
        public string Heading { get; set; }
        public List<OrderStatusInfo> Orders
        {
            get { return this; }
            set { Orders = value; }
        }
    }

public async Task<bool> BuildListviewData()
{

       await Task.Run(()=> {
          ObservableCollection<GroupedOrderModel> orderList = new ObservableCollection<GroupedOrderModel>();

         if (GlobalInfo.GlobalOrderList != null && GlobalInfo.GlobalOrderList.Count > 0)
          {    

                  List<string> Headers = GlobalInfo.GlobalOrderList.Select(x => x.Status).Distinct().OrderBy(x => x).ToList();

                   foreach (var item in Headers)
                   {
                       var oGroup = new GroupedOrderModel
                       {
                           Heading = item
                       };

                       var oList = GlobalInfo.GlobalOrderList.Where(x => x.Status == item).ToList();
                       foreach (var o in oList)
                          oGroup.Add(o);

                          orderList.Add(oGroup);
                     }

                ListOfOrdersGrouped = orderList;

          }
      }
}

   //Orders.cs page
   protected async override void OnAppearing()


   {

         await ovm.BuildListviewData();
         BindingContext = ovm;        
         base.OnAppearing();
   }
//The XAML

                 <ListView x:Name="ListViewOrdersList" HasUnevenRows="True" ItemsSource="{Binding ListOfOrdersGrouped}" IsGroupingEnabled="True">
                    <ListView.GroupHeaderTemplate>
                        <DataTemplate>
                            <ViewCell>
                                <Label Text="{Binding Heading}" Margin="10"/>
                            </ViewCell>
                        </DataTemplate>
                    </ListView.GroupHeaderTemplate>
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <ViewCell>
                                <Grid Padding="10">
                                    <Label Text="{Binding OrderNo}" FontSize="20" HorizontalOptions="Start"/>
                                </Grid>
                            </ViewCell>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
TResponse
  • 3,940
  • 7
  • 43
  • 63
lsuarez9
  • 11
  • 2
  • 1
    NotifyPropertyChanged("listOfOrdersGrouped"); - the name of your property is "ListofOrdersGrouped", not "listOfOrdersGrouped" – Jason May 08 '19 at 20:16
  • What happens if you don't use Task.Run(), and just directly run the code in BuildListviewData? – DavidS May 09 '19 at 01:43

2 Answers2

0

Change your ItemSource property's to

private listOfOrdersGrouped;
public ObservableCollection ListOfOrdersGrouped
{

    get { return listOfOrdersGrouped; }
    set {
        listOfOrdersGrouped = value;
        NotifyPropertyChanged("ListOfOrdersGrouped");
    }
}

The NotifyPropertyChanged should be:

NotifyPropertyChanged("ListOfOrdersGrouped");

So that the name matches that of the property your binding to in the XAML.

TResponse
  • 3,940
  • 7
  • 43
  • 63
  • Take a look at my answer here: https://stackoverflow.com/questions/54430503/xamarin-forms-tabbed-page-not-retrieving-data-from-in-onappearing/54430618#54430618 There is a sample project you can download which shows OnPropertyChanged usage and binding. It may assist you. – TResponse May 08 '19 at 22:08
0

For anyone struggling with the same problem:

The problem ended up being an issue with my view model being page specific (Such as OrdersViewModel.cs for my Orders.xaml.cs page). After I created an AppViewModel.cs for my App.xaml.cs page and dumped my OrdersViewModel properties in there under a new class named OrdersViewModel it all worked since the project runs the App.xaml and App.xaml.cs pages on startup before it does anything else. That's why binding was working in IOS and not Android. Android was attempting to process all code for every tabbed page before the binding could finish being instantiated (therefore, no data shown!).

However, I did tweak my code a little. Here are the changes:

namespace MyApp.ViewModels
{
    public class AppViewModel
    {
        public OrdersViewModel Ovm { get; set; }
    }

    public class OrdersViewModel : INotifyPropertyChanged
    {
        public ObservableCollection<GroupedOrderModel> ListOfOrdersGrouped
        {
            get { return listOfOrdersGrouped; }
            set
            {
                listOfOrdersGrouped = value;
                NotifyPropertyChanged("ListOfOrdersGrouped");
            }
        }

        public async Task<bool> BuildListviewData() 
        {
            //Same code here as mentioned above
        }
    }

     //Deleted OrderList class mentioned above

    public class GroupedOrderModel : ObservableCollection<OrderStatusInfo>
    {
        public string Heading { get; set; }
    }
}


//Xaml
<ListView x:Name="ListViewOrdersList" HasUnevenRows="True" ItemsSource="{Binding Ovm.ListOfOrdersGrouped}" IsGroupingEnabled="True">
     <ListView.GroupHeaderTemplate>
            <DataTemplate>
                  <ViewCell>
                      <Label Text="{Binding Heading}" Margin="10"/>
                   </ViewCell>
            </DataTemplate>
      </ListView.GroupHeaderTemplate>
      <ListView.ItemTemplate>
            <DataTemplate>
                 <ViewCell>
                     <Grid Padding="10">
                        <Label Text="{Binding OrderNo}" FontSize="20" HorizontalOptions="Start"/>
                      </Grid>
                 </ViewCell>
             </DataTemplate>
       </ListView.ItemTemplate>
</ListView>

Happy coding!

lsuarez9
  • 11
  • 2