Navigation Master Page Issue

Hello - I'm developing an Android/iOS app with Xamarin Forms which relies on the Navigation Master Detail page for its main navigation.
I've tested my app on Android and iOS simulators and it is working as intended. When I test it on a physical iPad however, the navigation menu is empty. The menu button and pop out work correctly, the pop out menu looks correct, but where there should be a list is just blank.

I've double checked font sizes, colors, label bindings etc - I don't think it's a UI problem.

The iOS simulator I'm using is running iOS 11.4 whereas the iPad I'm using is running iOS 9.3.5
Could it be the OS version?

Has anyone else seen this?

Posts

  • element014element014 Member ✭✭

    Update - tested this on an iPhone 6 Plus running iOS 11.4.1
    Same result as the iPad - it would appear my Navigation Master Detail page is only working on simulators...

    OS version ruled out as a cause.

    Any help would be appreciated.

  • element014element014 Member ✭✭
    edited August 2018

    My Code For reference:

    Code Behind:

    public partial class NavigationMaster : ContentPage
    {
    public ListView ListView;

        public NavigationMaster()
        {
            Icon = Services.PlatformImage.Resolver("menu.png");
            InitializeComponent();
    
            ListView = MenuItemsListView;
            ListView.BindingContext = new NavigationMasterViewModel();
        }
    
        class NavigationMasterViewModel : INotifyPropertyChanged
        {
            public ObservableCollection<NavigationMenuItem> MenuItems { get; set; }
    
            public NavigationMasterViewModel()
            {
                MenuItems = new ObservableCollection<NavigationMenuItem>(new[]
                {
                    new NavigationMenuItem { Id = 1, Title = "Item1", Icon = "menu_inbox.png", TargetType = typeof(Views.Projects)},
                    new NavigationMenuItem { Id = 2, Title = "Item2", Icon = "menu_inbox.png", TargetType = typeof(Views.Tickets)},
                    new NavigationMenuItem { Id = 3, Title = "Item3", Icon = "menu_inbox.png", TargetType = typeof(Views.Documents)},
                    new NavigationMenuItem { Id = 4, Title = "Item4", Icon = "menu_inbox.png", TargetType = typeof(Views.Calendar)},
                    new NavigationMenuItem { Id = 4, Title = "Item5", Icon = "menu_inbox.png", TargetType = typeof(Views.Discussion)},
                });
            }
            #region INotifyPropertyChanged Implementation
            public event PropertyChangedEventHandler PropertyChanged;
            void OnPropertyChanged([CallerMemberName] string propertyName = "")
            {
                if (PropertyChanged == null)
                    return;
    
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
            #endregion
        }
    }
    

    }

    And XAML

  • seanydaseanyda GBMember ✭✭✭✭✭

    I've not tested this, Just modified it in this forum text editor, but try this... replace your view model with the below

    class NavigationMasterViewModel : INotifyPropertyChanged
        {
        private ObservableCollection<NavigationMenuItem> _menuItems = new ObservableCollection<NavigationMenuItem>();
            public ObservableCollection<NavigationMenuItem> MenuItems { 
            get { return _menuItems; }
            set { 
                _menuItems = value;
                OnPropertyChanged(nameof(MenuItems));
            }
    }
    
            public NavigationMasterViewModel()
            {
                MenuItems = new ObservableCollection<NavigationMenuItem>(new[]
                {
                    new NavigationMenuItem { Id = 1, Title = "Item1", Icon = "menu_inbox.png", TargetType = typeof(Views.Projects)},
                    new NavigationMenuItem { Id = 2, Title = "Item2", Icon = "menu_inbox.png", TargetType = typeof(Views.Tickets)},
                    new NavigationMenuItem { Id = 3, Title = "Item3", Icon = "menu_inbox.png", TargetType = typeof(Views.Documents)},
                    new NavigationMenuItem { Id = 4, Title = "Item4", Icon = "menu_inbox.png", TargetType = typeof(Views.Calendar)},
                    new NavigationMenuItem { Id = 4, Title = "Item5", Icon = "menu_inbox.png", TargetType = typeof(Views.Discussion)},
                });
            }
            #region INotifyPropertyChanged Implementation
            public event PropertyChangedEventHandler PropertyChanged;
            void OnPropertyChanged([CallerMemberName] string propertyName = "")
            {
                if (PropertyChanged == null)
                    return;
    
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
            #endregion
        }
    
  • seanydaseanyda GBMember ✭✭✭✭✭

    also the code here

    public ListView ListView;
    
        public NavigationMaster()
        {
            Icon = Services.PlatformImage.Resolver("menu.png");
            InitializeComponent();
    
            ListView = MenuItemsListView;
            ListView.BindingContext = new NavigationMasterViewModel();
        }
    

    This is breaking the MVVM pattern. We don't want to be using x:Name in the XAML if possible. Replace with the below

    public partial class NavigationMaster : ContentPage
    {
        public NavigationMaster()
        {
            Icon = Services.PlatformImage.Resolver("menu.png");
            InitializeComponent();
            BindingContext = new NavigationMasterViewModel();
        }
    
    

    ListView will inherit the ContentPage's ViewModel unless stated otherwise. If this is the ViewModel which handles all the Binding for NavigationMaster then do it like the above. If not, set the BindingContext on that StackLayout containing the ListView.

  • element014element014 Member ✭✭

    Thanks for the replies!

    Same result - works perfectly on the simulator, but on either device the menu is empty.

  • seanydaseanyda GBMember ✭✭✭✭✭

    @element014 said:
    Thanks for the replies!

    Same result - works perfectly on the simulator, but on either device the menu is empty.

    Are the separator lines showing at all for the ListView? You need to find out if its a case of the View just not appearing at all, or it not being populated.

  • element014element014 Member ✭✭

    I've enabled them to check - the view is definitely there.
    The empty header is a result of other UI testing I've done to rule out possibilities.

  • seanydaseanyda GBMember ✭✭✭✭✭

    @element014 said:
    I've enabled them to check - the view is definitely there.
    The empty header is a result of other UI testing I've done to rule out possibilities.

    If that's the case then it's an issue of something happening quicker or slower on the simulator in comparison to the physical devices I think. Breakpoint this line - Does it ever get fired?

    PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
    
  • element014element014 Member ✭✭

    On the devices it does not

  • element014element014 Member ✭✭

    Nor does it on the simulator

  • seanydaseanyda GBMember ✭✭✭✭✭

    @element014 said:
    Nor does it on the simulator

    Are you using the code examples I sent you? Change the property to this and try again.

    private ObservableCollection<NavigationMenuItem> _menuItems = new ObservableCollection<NavigationMenuItem>();
            public ObservableCollection<NavigationMenuItem> MenuItems { 
            get { return _menuItems; }
            set { 
                _menuItems = value;
                OnPropertyChanged(nameof(MenuItems));
            }
    }
    
  • element014element014 Member ✭✭
    edited August 2018

    Yes, I have been using that since your initial reply.

    The break at: PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName)); doesn't fire.

  • seanydaseanyda GBMember ✭✭✭✭✭

    @element014 said:
    Yes, I have been using that since your initial reply.

    The break at: PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName)); doesn't fire.

    That is probably your issue. Long shot, but I don't use the PropertyChanged method you used, Mine is slightly different.. Try this

    public event PropertyChangedEventHandler PropertyChanged;
    
            protected virtual void OnPropertyChanged(string propertyName)
            {
                var changed = PropertyChanged;
                if (changed != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
    

    I believe if you get that line to fire, your list will populate and show you the information.

  • element014element014 Member ✭✭

    I think you're right. No change with your PropertyChanged method, but it's pointing me in the right direction so thank you!

  • element014element014 Member ✭✭
    I have a duplicate ID in my list, the product of copy paste... I've corrected it for the off chance it was causing this issue or another.

    Not surprised, it wasn't the problem. Still have an empty menu on physical devices only.
  • element014element014 Member ✭✭
    edited August 2018

    I've put a breakpoint on every single line I can, not a single one is triggered when the app is run on a physical device, but every single one is triggered with the simulator.

    "Initialize Component()" doesn't fire....
    "BindingContext = new NavigationMasterViewModel()" doesn't fire...

    But only on physical devices...

  • element014element014 Member ✭✭
    Release and Debug builds have the same result on physical devices.

    Do I need to ditch the pop out navigation design?
    I would prefer to keep it.
  • element014element014 Member ✭✭

    Came back to this - breakpoints now fire (nothing has changed), blaming VS for that nonsense.

    My menu is still blank. Anyone have any ideas?

Sign In or Register to comment.