StackLayout within a ListView Disappears when refreshing

For some reason, on iOS, when I try to pull to refresh, anything that has a StackLayout within the ViewCell just disappears. Does this have to do with the resizing restriction iOS has?

Answers

  • jobarkejobarke USXamarin Team Xamurai

    There could be something in your code that is causing the objects to clear.
    Do you have a sample?

  • nefgrixisnefgrixis Member ✭✭
    edited September 2018

    There was. I figured it out. I had a custom View with some Bindable Properties that were not being notified of changes. I took the views from that class and put it in the containing ListView and then it was working after. I had another problem with SignalR and adding items to the ItemsSource. Basically what I'm trying to do is to add an item in the nested horizontal ScrollView ItemsSource

    ActivityVM

        public class ActivityVM : INotifyPropertyChanged
        {
            public void Remove()
            {
                ActivityList.Remove("Prepare");
                OnPropertyChanged("ActivityList");
            }
    
            private ObservableDictionary<string, List<Activity>> _activityList = new ObservableDictionary<string, List<Activity>>();
            public ObservableDictionary<string, List<Activity>> ActivityList
            {
                get
                {
                    return _activityList;
                }
                set
                {
                    _activityList = value;
                    OnPropertyChanged("ActivityList");
                }
            }
    
            public ObservableDictionary<string, List<Activity>> UpcomingActivityList = new ObservableDictionary<string, List<Activity>>();
    
            //When an Activity is selected this set and retrieved by the ActivityDetailsPage
            private Activity _activity = new Activity();
            public Activity Activity
            {
                get
                {
                    return _activity;
                }
                set
                {
                    _activity = value;
                    OnPropertyChanged("Activity");
                }
            }
    
            public void SetListeners()
            {
                HubConnectionManager.Connection.On<string, Activity>("NewActivity", (catName, act) =>
                {
                    Debug.WriteLine($"{catName}, {act.ToString()}");
                    //Device.BeginInvokeOnMainThread(() =>
                    //{
                    //    Application.Current.MainPage.DisplayAlert("SignalR Message", $"CategoryName: {catName} \n ID: {act.ID}", "OK");
                    //});
                    NewActivity(catName, act);
                });
    
                HubConnectionManager.Connection.On<string, Activity>("UpdateActivity", (catName, act) =>
                {
                    Debug.WriteLine($"***** CategoryName: {catName}");
                    Debug.WriteLine($"***** Object: {act.ToString()}");
    
                    UpdateActivity(catName, act);
                });
    
                if (HubConnectionManager.IsConnectionClosed)
                {
                    HubConnectionManager.InitConnection();
                }
            }
    
            public void UpdateActivity(string catName, Activity act)
            {
                if (ActivityList.Count == 0)
                {
                    return;
                }
                var tempList = ActivityList[catName];
    
                var index = tempList.FindIndex(s => s.ID.Equals(act.ID));
    
                tempList[index] = act;
    
                ActivityList[catName] = tempList;
                OnPropertyChanged("ActivityList");
            }
    
            public void NewActivity(string catName, Activity act)
            {
                if (ActivityList.Count == 0)
                {
                    return;
                }
                if (ActivityList.ContainsKey(catName))
                {
                    ActivityList[catName].Add(act);
                    OnPropertyChanged("ActivityList");
                }
                else
                {
                    var newCatList = new List<Activity>();
                    ActivityList.Add(catName, newCatList);
                    OnPropertyChanged("ActivityList");
                }
            }
    
            public void InitActivityList(Dictionary<string, List<Activity>> dict)
            {
                ActivityList = new ObservableDictionary<string, List<Activity>>(dict);
            }
    
            // Getting the Activities for the Feed on Home Page
            public async Task  GetActivities()
            {
                try
                {
                    string url = Constants.WebApiUrl + "/acts";
    
                    // DOCS: String extension method to make api calls and serialize and de-serialize repsonse data automatically (Flurl)
                    //Dictionary<string, List<Activity>> res = await url.WithTimeout(10).GetJsonAsync<Dictionary<string, List<Activity>>>();
                    var res = await url.WithTimeout(15).GetJsonAsync<ObservableDictionary<string, List<Activity>>>();
                    StateManager.SaveLastActivityList(res);
                    ActivityList = res;
                }
                catch (FlurlHttpTimeoutException ex)
                {
                    Debug.WriteLine(ex);
                    ErrorHandler.ShowErrorIf("Activity Retrieval Timedout", "Connection timed out. Please check your connection and try again");
                    ActivityList = StateManager.GetLastActList();
                    //await Application.Current.MainPage.DisplayAlert("Server Error", "Connection timed out. Please check your connection or try again later.", "Okay");
                }
                catch (FlurlHttpException ex)
                {
                    Debug.WriteLine(ex);
                    ErrorHandler.ShowErrorIf("Server Error", "Check your connection and try again");
                    ActivityList = StateManager.GetLastActList();
                    //await Application.Current.MainPage.DisplayAlert("Unable to retreive list of activities", "Check your connection and try again", "Okay");
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex);
                    Analytics.TrackError(ex);
                    ErrorHandler.ShowErrorIf("Unable to retrieve activities", "Try again later. If problem persists, send a description of your problem (Menu Icon -> Feedback)");
                    ActivityList = StateManager.GetLastActList();
                    //await Application.Current.MainPage.DisplayAlert("Unable to retreive list of activities", "Check your connection and try again", "Okay");
                }
            }
    }
    

    TestPage.xaml

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:custom="clr-namespace:BizPass.Controls"
                 xmlns:local="clr-namespace:BizPass.Components"
                 xmlns:horizontallist="clr-namespace:HorizontalList;assembly=HorizontalList"
                 x:Class="BizPass.Test.TestPage">
        <ContentPage.Content>
            <!--<video:VideoPlayer Source="https://storage.googleapis.com/coverr-main/mp4/The-Launch.mp4"
                                   AutoPlay="True"
                                   HorizontalOptions="Fill"
                                   VerticalOptions="Fill"
                                   BackgroundColor="Black"/>-->
            <StackLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
                <Button x:Name="btn" Text="hello" HorizontalOptions="Center"/>
            <ListView  x:Name="LV" SelectionMode="None" CachingStrategy="RecycleElement">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <custom:CustomFrame Padding="0,5,0,0" Margin="0,10,0,0" >
                                <StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
                                    <Label Style="{StaticResource bold}" FontSize="Large" TextColor="#c4950b" Margin="10,0,0,0"  x:Name="labelName" Text="{Binding Key}" />
                                    <horizontallist:HorizontalList SelectedItemChanged="_onItemSelected" x:Name="hList" ListOrientation="Horizontal" ItemsSource="{Binding Value}">
                                        <horizontallist:HorizontalList.ItemTemplate >
                                            <DataTemplate>
                                                <StackLayout Orientation="Horizontal" Padding="0,0,0,5">
                                                    <local:ActivityItemNew Padding="10,0,5,0" VerticalOptions="FillAndExpand"/>
                                                    <BoxView VerticalOptions="Fill" HorizontalOptions="End" Color="LightGray" Opacity="0.5" WidthRequest="2" x:Name="sepLine"/>
                                                </StackLayout>
                                            </DataTemplate>
                                        </horizontallist:HorizontalList.ItemTemplate>
                                    </horizontallist:HorizontalList>
                                </StackLayout>
                            </custom:CustomFrame>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
            </StackLayout>
        </ContentPage.Content>
    </ContentPage>
    

    TestPage.Xaml.cs

    public partial class TestPage : ContentPage
        {
            TestVM _vm = new TestVM();
            public TestPage()
            {
                InitializeComponent();
    
                BindingContext = _vm;
                //_vm.Add(DateTime.Now.Ticks.ToString());
                //LV.SetBinding(ListView.ItemsSourceProperty, "TestList");
                _vm.SetListeners();
    
                switch (Device.RuntimePlatform)
                {
                    case "Android":
                        LV.HasUnevenRows = true;
                        break;
                    case "iOS":
                        var lvHeight = (App.DisplayScreenWidth * .55);
                        LV.RowHeight = Convert.ToInt32(lvHeight);
    
                        break;
                }
                LV.SetBinding(ListView.ItemsSourceProperty, "ActivityList");
                LV.IsPullToRefreshEnabled = true;
                LV.Refreshing += async (sender, ev)=> 
                {
                    //_vm.Add(DateTime.Now.ToString());
                    //LV.RemoveBinding(ListView.ItemsSourceProperty);
                    //LV.ItemsSource = null;
                    await _vm.GetActivities();
                    //_vm.Remove();
                    //LV.ItemsSource = _vm.ActivityList;
                    LV.IsRefreshing = false;
                };
            }
    
            protected override async void OnAppearing()
            {
                base.OnAppearing();
                await _vm.GetActivities();
            }
    
            private bool _isNavigating = false;
            public ICommand SelectedCommand
            {
                set;
                get;
            }
            async void _onItemSelected(object sender, EventArgs args)
            {
                if (_isNavigating)
                {
                    _isNavigating = false;
                    return;
                }
                else
                {
                    _isNavigating = true;
                    HorizontalList.HorizontalList item = (HorizontalList.HorizontalList)sender;
                    Activity act = (Activity)item.SelectedItem;
    
                    // Tracks the Activity and it's code for reference
                    //Analytics.TrackAction("Act", $"{act.ID}", (bool)Application.Current.Properties["lowVis"], (string)Application.Current.Properties["Tier"], (string)Application.Current.Properties["PantherID"]);
    
                    await Application.Current.MainPage.Navigation.PushAsync(new Pages.ActivityDetailPage(act.ID, act.Points));
                }
            }
        }
    
  • nefgrixisnefgrixis Member ✭✭

    I'm also getting these messages
    [0:] Binding: 'Value' property not found on '[Engage, System.Collections.Generic.List`1[BizPass.Models.Activity]]', target property: 'HorizontalList.HorizontalList.ItemsSource'

Sign In or Register to comment.