locked
How to update a Listview in Sub-Shell item navigation, or contentpage to contentpage in a Shell? RRS feed

  • Question

  • User387160 posted

    What I want to accomplish:

    When a user presses the back button on shell when in a particular content page, an api request is made to update the listview. OR update the ListView with fluff until the next API request.

    What I've tried: 1) PopAsync the form so that users cannot return to the form once completed (to prevent multiple accidental api post requests). Goes to review page. If back button is tapped, the OnAppearing method of the Content page that contains the list does an API request to update the Observable Collection of list items.

    This works only when navigating from one Shell Flyout item to another, it does not work when navigating between Content Pages of a given Shell Flyout Item.

    2) Using OnDisappearing of the review page sends a Message Center message to the Main Content page to update the list view.

    Never works.

    3) When Post request is made on the form going directly to the Shell.Current.GoToAsync("///MainContent");

    This simply returns me to the outdated version of the observable collection page.

    So, in code this looks like:

    Shell Item

    <FlyoutItem Route="LoggedIn" Title="Calendars">
            <FlyoutItem.Icon>
                <FontImageSource
                    FontFamily="{StaticResource FontAwesomeRegular}"
                    Glyph="{x:Static fontawesome:FontAwesomeIcons.CalendarAlt}"
                    Color="DarkSeaGreen"
                    Size="24">
                </FontImageSource>
            </FlyoutItem.Icon>
            <ShellSection>
                <ShellContent Style="{StaticResource MyShell}" ContentTemplate="{DataTemplate mobile:CalendarListPage}" />
            </ShellSection>
        </FlyoutItem>
    

    Main Page

    public partial class CalendarListPage : ContentPage
    {
        public CalendarListPage()
        {
            InitializeComponent();
            BindingContext = new CalendarListViewModel(this);
            BackgroundColor = Color.FromHex("#ededed");
        }
    
        protected override void OnAppearing()
        {
            base.OnAppearing();
            BindingContext = new CalendarListViewModel(this);
        }
    // Irrelevant code...
    

    Relevant MainPageViewModel Code

        public CalendarListViewModel(Page page)
        {
            _page = page;
            CalendarList = new ObservableCollection<CalendarListModelItem>();
            MessagingCenter.Subscribe<CalendarListModelItem>(this, "AddNew", (item) =>
            {
                CalendarList.Add(item);
            });
            AddCalendarListItems();
        }
    
        private void AddCalendarListItems()
        {
            // Api response of list of CalendarListModelItems
            try
            {
                var response = _ApiService.GetCalendarList();
    
                foreach (var item in response)
                    {
                        CalendarList.Add(item);
                    }            
            }
            catch (Exception e)
            {
                // throw error
            }
        }
    

    CreateNewPage only contains form and binds to view model

    CreateNewCalendarViewModel

        private async Task CreateAsync()
        {
            var response = await _apiService.CreateCalendar(CreateCalendarModel);
    
            if (!string.IsNullOrWhiteSpace(response))
            {
                await _page.Navigation.PushAsync(new PublicCalendarPage(response));
                _page.Navigation.RemovePage(_page);
            }
            else
            {
                // not relevant 
            }
        }
    

    PublicCalendarPage

        protected override void OnDisappearing()
        {
            base.OnDisappearing();
    
            var item = new CalendarListModelItem
            {
                AccessCode = AccessCode,
                Name = "Some Name",
                StartDate = _calendarModel.StartDate,
                EndDate = _calendarModel.EndDate
            };
    
            MessagingCenter.Send(item, "AddNew");
    
        }
    

    Any help is appreciated. Thanks!

    Sunday, September 1, 2019 8:55 PM

Answers

  • User382871 posted

    To update a ListView in ContentPage. Have you tried using an ObservableCollection for the ListView? As soon as you update an item from this ObservableCollection the view will render and delete the listview item for you.

    When a user presses the back button on shell when in a particular content page...

    Use the Back button behavior in Shell to create a custom button, the may help you. <ContentPage ...>
    <Shell.BackButtonBehavior> <BackButtonBehavior Command="{Binding BackCommand}" IconOverride="back.png" />
    </Shell.BackButtonBehavior> ... </ContentPage>

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Wednesday, September 4, 2019 9:14 AM

All replies

  • User382871 posted

    This works only when navigating from one Shell Flyout item to another, it does not work when navigating between Content Pages of a given Shell Flyout Item.

    You can use routes to navigate to any page in the application. Routes can be defined on FlyoutItem, Tab, and ShellContent objects.

    await Shell.Current.GoToAsync("//animals/monkeys");

    Check the tutorial about Shell Navigation. https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/shell/navigation

    Monday, September 2, 2019 10:18 AM
  • User387160 posted

    I may have miscommunicated something... the issue isn't with the routing, that works. it's getting a fresh api request to fire prior to the page loading during content page to content page navigation within the shell.

    Monday, September 2, 2019 8:13 PM
  • User387160 posted

    I forgot to mention I'm using VS2019 on XF 4.2

    Monday, September 2, 2019 8:37 PM
  • User382871 posted

    To update a ListView in ContentPage. Have you tried using an ObservableCollection for the ListView? As soon as you update an item from this ObservableCollection the view will render and delete the listview item for you.

    When a user presses the back button on shell when in a particular content page...

    Use the Back button behavior in Shell to create a custom button, the may help you. <ContentPage ...>
    <Shell.BackButtonBehavior> <BackButtonBehavior Command="{Binding BackCommand}" IconOverride="back.png" />
    </Shell.BackButtonBehavior> ... </ContentPage>

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Wednesday, September 4, 2019 9:14 AM
  • User387160 posted

    good call.

    Thursday, September 5, 2019 1:46 AM