Menu icon and title not showing on UWP, works on Android and iOS

Hi,
I seem to be having a problem when I try to add a TabbedPage to my MasterDetailPage.

Here is the structure of the app

MainPage is MasterDetailPage
Master is a ContentPage with a menu
Detail is a TabbedPage with children

Each child page of the TabbedPage is wrapped in a NavigationPage.

On my TabbedPage, I am adding tabs like this:

    public TabbedNavPage()
    {
        InitializeComponent();

        // Set pages for tabs
        this.Children.Add(new NavigationPage(new CustomersPage()) { Icon = "customers.png", Title = "Customers" });
        //this.Children.Add(new CustomersPage() { Title = "Customers" });
        this.Children.Add(new NavigationPage(new ContactsPage()) { Icon = "contacts.png", Title = "Contacts" });
        this.Children.Add(new NavigationPage(new CalendarPage()) { Icon = "calendar.png", Title = "Calendar" });
        this.Children.Add(new NavigationPage(new TasksPage()) { Icon = "tasks.png", Title = "Tasks" });
        this.Children.Add(new NavigationPage(new EmployeesPage()) { Icon = "employees.png", Title = "Employees" });


    }

On Android and iOS, this works fine, each tab shows the title and icon for the tab, and when I tap on a tab, the navigation bar on the top changes to the appropriate title. The menu button is there and I can open the master view and see the menu.
image

On UWP, its a whole different story
image

Now, If I instead wrap the TabbedPage inside a NavigationPage, and remove the NavigationPages from around the tab pages, then UWP will work and show the icon and title, however, the Title will always be the title of the MasterDetailPage, and not the tab pages (this happens across all platforms)

Any idea what I might be doing wrong?
Here's the code I use to set the content of the MasterDetailPage:

    // Keep reference to the master and detail pages
    private NavigationMenuPage _menu;
    //private NavigationPage _detail;
    private TabbedNavPage _tabs;

    public MainNavigationPage()
    {
        InitializeComponent();

        // Create page instances
        _menu = new NavigationMenuPage();
        _tabs = new TabbedNavPage();
        //_detail = new NavigationPage(_tabs);


        // Set pages
        Master = _menu;
        Detail = _tabs; //_detail;


        // Set the events to handle navigation from main menu
        _menu.Menu.ItemSelected += Menu_ItemSelected;

    }
Tagged:

Answers

  • DerProgrammiererDerProgrammierer DEMember ✭✭✭
    edited September 2016

    @neptunecentury have you found a solution for this yet?

    And while being on this topic, does anyone know how to change the titlecolor? I have a dark toolbar, so a black-colored text is hard to read.

    EDIT: Some additional information
    This is my code. Works perfectly fine for iOS and Android (icons are displayed), but for UWP it doesn't show icons:

    Code:

    <TabbedPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms" prism:ViewModelLocator.AutowireViewModel="True" xmlns:local="clr-namespace:One;assembly=One" xmlns:v="clr-namespace:One.Views;assembly=One" xmlns:i18n="clr-namespace:One;assembly=One" x:Class="One.Views.ChatsTabbedPage" Title="Chats" BarBackgroundColor="{StaticResource navBarBackgroundColor}" x:Name="TabPage" > <TabbedPage.Children> <v:ChatsPhonePage Title="Chats" Icon="ic_chat.png" Appearing="Handle_Appearing" > </v:ChatsPhonePage> <v:KontaktePage Title="{i18n:Translate Text=kontakte}" Icon="ic_contacts.png"> </v:KontaktePage> </TabbedPage.Children> </TabbedPage>

    Result:

  • LeeMcPhersonLeeMcPherson USMember

    Still having the same issue.

    Mine is even simpler: MasterDetailPage.Detail -> NavigationPage -> ContentPage

    It shows beautifully in Android (although I had to disable the navigationbar and backbutton on ContentPage).
    I don't know about iOS yet.

    UWP on mobile shows the title of my MasterDetailPage.Master's ContentPage, but there is no icon showing. There's no way to get to the Master menu and navigate. Swiping to the right doesn't work either.

  • LeeMcPhersonLeeMcPherson USMember

    Ah-ha! It seems that when there is more than one NavigationPage, the UWP project has trouble. I was using a base NavigationPage to launch the MasterDetailPage (and to display any modal pages). Then my MasterDetailPage's Detail property had its own NavigationPage.

    Removing the first one and just using a NavigationPage within the detail part of MasterDetailPage solved my problem. It certainly shows there's a bug in the UWP part of forms though.

    NeptuneCentury: couldn't you just databind the Title property to the CurrentPage Property of your TabbedPage?
    see: https://developer.xamarin.com/api/type/Xamarin.Forms.MultiPage`1/

  • SmeSme USMember ✭✭✭
    edited October 2016

    Another way to do it, is by doing this in the MainTabbedPage.xaml.cs file:

    public void MainTabbedPage()
    {
        ...
        this.CurrentPageChanged += CurrentPageHasChanged;
    }
    
    protected void CurrentPageHasChanged(object sender, EventArgs e)
    {
        this.Title = this.CurrentPage.Title;
    }
    

    As long as each 'tabbed' page has a title property set, then it will update the title of the tabbed page

    Though you might need to initally set the title of the page in the MainTabbedPage constructor to that of your first tabbed page. IE, this.Title = "Tab 1 Title";

  • DerProgrammiererDerProgrammierer DEMember ✭✭✭
    edited October 2016

    @LeeMcPherson @Sme But why are the icons not visible on UWP?

  • SmeSme USMember ✭✭✭
    edited October 2016

    I think you need a custom renderer to display the icons in UWP

    Also, to change the title color, when you create the tabbed page, you can set the property of its title bar color

  • DerProgrammiererDerProgrammierer DEMember ✭✭✭

    @Sme said:
    I think you need a custom renderer to display the icons in UWP

    Also, to change the title color, when you create the tabbed page, you can set the property of its title bar color

    It's good to know that I can change the title bar color. Unfortunately, I haven't found a way to do so yet.

    This is where I create the TabbedPage:

    <?xml version="1.0" encoding="UTF-8"?>
    <TabbedPage 
            xmlns="http://xamarin.com/schemas/2014/forms" 
            xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
            xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms" 
            prism:ViewModelLocator.AutowireViewModel="True" 
            xmlns:local="clr-namespace:One;assembly=One"
            xmlns:v="clr-namespace:One.Views;assembly=One"
            xmlns:i18n="clr-namespace:One;assembly=One"
            x:Class="One.Views.ChatsTabbedPage"
            Title="Chats"
            BarBackgroundColor="{StaticResource navBarBackgroundColor}" x:Name="TabPage" >
        <TabbedPage.Children>
                <v:ChatsPhonePage 
                    Title="Chats"
                    Icon="ic_chat.png"
                    Appearing="Handle_Appearing"
                    >
                </v:ChatsPhonePage>
                <v:KontaktePage Title="{i18n:Translate Text=kontakte}"
                    Icon="ic_contacts.png">
                </v:KontaktePage>
        </TabbedPage.Children>
    </TabbedPage>
    

    I can't find a property for the title color...

  • SmeSme USMember ✭✭✭
    edited October 2016

    @DerProgrammierer said:

    @Sme said:
    I think you need a custom renderer to display the icons in UWP

    Also, to change the title color, when you create the tabbed page, you can set the property of its title bar color

    It's good to know that I can change the title bar color. Unfortunately, I haven't found a way to do so yet.

    This is where I create the TabbedPage:

    <?xml version="1.0" encoding="UTF-8"?>
    <TabbedPage 
          xmlns="http://xamarin.com/schemas/2014/forms" 
          xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
          xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms" 
          prism:ViewModelLocator.AutowireViewModel="True" 
          xmlns:local="clr-namespace:One;assembly=One"
          xmlns:v="clr-namespace:One.Views;assembly=One"
          xmlns:i18n="clr-namespace:One;assembly=One"
          x:Class="One.Views.ChatsTabbedPage"
          Title="Chats"
          BarBackgroundColor="{StaticResource navBarBackgroundColor}" x:Name="TabPage" >
      <TabbedPage.Children>
              <v:ChatsPhonePage 
                  Title="Chats"
                  Icon="ic_chat.png"
                  Appearing="Handle_Appearing"
                  >
              </v:ChatsPhonePage>
              <v:KontaktePage Title="{i18n:Translate Text=kontakte}"
                  Icon="ic_contacts.png">
              </v:KontaktePage>
      </TabbedPage.Children>
    



    I can't find a property for the title color...

    Here is the code I'm using

    App.Current.MainPage = new NavigationPage(new MainTabbedPage()) { BarBackgroundColor = Color.FromHex("#333333"), BarTextColor = Color.White };

    Oops, I made a mistake. The properties are not in the Tabbed Page. Yes, it seems like the tabbed page needs to be wrapped in a navigation page, and its actually the navigation page's bar and text color (the tabs in the tabbed page do not change color unfortunately..)

    But again I think it can be solved with a custom renderer (I myself haven't created any yet for my app, I was planning on working on that towards the end of the development cycle). But if I find a solution I'll let you know too

    Edit:
    Actually I looked into it further, and TabbedPage also has properties BarBackgroundColor and BarTextColor. Try settings those and see what happens.

  • DerProgrammiererDerProgrammierer DEMember ✭✭✭

    @Sme said:

    @DerProgrammierer said:

    @Sme said:
    I think you need a custom renderer to display the icons in UWP

    Also, to change the title color, when you create the tabbed page, you can set the property of its title bar color

    It's good to know that I can change the title bar color. Unfortunately, I haven't found a way to do so yet.

    This is where I create the TabbedPage:

    <?xml version="1.0" encoding="UTF-8"?>
    <TabbedPage 
            xmlns="http://xamarin.com/schemas/2014/forms" 
            xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
            xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms" 
            prism:ViewModelLocator.AutowireViewModel="True" 
            xmlns:local="clr-namespace:One;assembly=One"
            xmlns:v="clr-namespace:One.Views;assembly=One"
            xmlns:i18n="clr-namespace:One;assembly=One"
            x:Class="One.Views.ChatsTabbedPage"
            Title="Chats"
            BarBackgroundColor="{StaticResource navBarBackgroundColor}" x:Name="TabPage" >
        <TabbedPage.Children>
                <v:ChatsPhonePage 
                    Title="Chats"
                    Icon="ic_chat.png"
                    Appearing="Handle_Appearing"
                    >
                </v:ChatsPhonePage>
                <v:KontaktePage Title="{i18n:Translate Text=kontakte}"
                    Icon="ic_contacts.png">
                </v:KontaktePage>
        </TabbedPage.Children>
    



    I can't find a property for the title color...

    Here is the code I'm using

    App.Current.MainPage = new NavigationPage(new MainTabbedPage()) { BarBackgroundColor = Color.FromHex("#333333"), BarTextColor = Color.White };

    Oops, I made a mistake. The properties are not in the Tabbed Page. Yes, it seems like the tabbed page needs to be wrapped in a navigation page, and its actually the navigation page's bar and text color (the tabs in the tabbed page do not change color unfortunately..)

    But again I think it can be solved with a custom renderer (I myself haven't created any yet for my app, I was planning on working on that towards the end of the development cycle). But if I find a solution I'll let you know too

    As NMackay told me, one has to change PivotItemHeader to change the TabbedPage Items.

  • DerProgrammiererDerProgrammierer DEMember ✭✭✭

    Sorry for double-posting... I can't edit after 60 minutes... Just for clarification, I managed to change the color of the PivotHeaderItems now (Thanks again to NMackay):

    http://forums.xamarin.com/discussion/comment/226477/#Comment_226477

  • DerProgrammiererDerProgrammierer DEMember ✭✭✭
    edited December 2016

    Regarding the original question of this thread: Any update on this?

    • Is the Xamarin team aware of this? I guess it just hasn't been implemented yet.
    • Did anyone find a workaround to make icons visible for TabbedPage Children on UWP?

    @LeeMcPherson said:
    Ah-ha! It seems that when there is more than one NavigationPage, the UWP project has trouble. I was using a base NavigationPage to launch the MasterDetailPage (and to display any modal pages). Then my MasterDetailPage's Detail property had its own NavigationPage.

    Removing the first one and just using a NavigationPage within the detail part of MasterDetailPage solved my problem. It certainly shows there's a bug in the UWP part of forms though.

    NeptuneCentury: couldn't you just databind the Title property to the CurrentPage Property of your TabbedPage?
    see: https://developer.xamarin.com/api/type/Xamarin.Forms.MultiPage`1/

    This is my original navigation:

    await _navigationService.NavigateAsync("OneNavigationPage/ChatsTabletMDPage/MessagePhonePage", animated: false);

    So I tried to use a NavigationPage just for the Details, but neither did this make the icons appear on my UWP app:

    await _navigationService.NavigateAsync("ChatsTabletMDPage/OneNavigationPage/MessagePhonePage", animated: false);

  • SmeSme USMember ✭✭✭

    @DerProgrammierer said:
    Regarding the original question of this thread: Any update on this?

    • Is the Xamarin team aware of this? I guess it just hasn't been implemented yet.
    • Did anyone find a workaround to make icons visible for TabbedPage Children on UWP?

    @LeeMcPherson said:
    Ah-ha! It seems that when there is more than one NavigationPage, the UWP project has trouble. I was using a base NavigationPage to launch the MasterDetailPage (and to display any modal pages). Then my MasterDetailPage's Detail property had its own NavigationPage.

    Removing the first one and just using a NavigationPage within the detail part of MasterDetailPage solved my problem. It certainly shows there's a bug in the UWP part of forms though.

    NeptuneCentury: couldn't you just databind the Title property to the CurrentPage Property of your TabbedPage?
    see: https://developer.xamarin.com/api/type/Xamarin.Forms.MultiPage`1/

    This is my original navigation:

    await _navigationService.NavigateAsync("OneNavigationPage/ChatsTabletMDPage/MessagePhonePage", animated: false);

    So I tried to use a NavigationPage just for the Details, but neither did this make the icons appear on my UWP app:

    await _navigationService.NavigateAsync("ChatsTabletMDPage/OneNavigationPage/MessagePhonePage", animated: false);

    Do you mean icons on the tabs themselves?

  • SmeSme USMember ✭✭✭
    edited December 2016

    Also, I think because icons are not 'standard' on the pivot items in UWP, that the Xamarin team probably has no intention of implementing them for UWP, leaving us to rely on custom renderers.

    I was able to add icons to the tabs in UWP, though the solution isn't perfect. The first problem I encountered was trying to create an extended class of the ContentPage class, which I was able to do but in the Xaml, I wasn't able to figure out how to use it (ie, instead of <ContentPage></ContentPage> I tried to use <ExtendedContentPage></ExtendedContentPage>, but it would throw an error).

    Instead of searching to solve that, instead I just created a new property on each of the Tabbed Page's children (in the xaml.cs files for each child page). I had to create a new property because I had a problem converting the FileImageSource to UWP's BitmapIcon's UriSource property. Again maybe there is a better solution that what I have here (im sure there is) but it works for me so I'm happy with it for now.

    First, you need this class:

    public static class BindableObjectExtensions
        {
            public static T GetValue<T>(this BindableObject bindableObject, BindableProperty property)
            {
                return (T)bindableObject.GetValue(property);
            }
        }
    

    Then, in each of the child page's xaml.cs files, add this (again if you can find a way to successfully extend a ContentPage and use that in the Xaml, then just add this following code to the ExtendedContentPage class, and have the child pages be of that type instead of ContentPage):

            public static readonly BindableProperty UWPIconProperty = BindableProperty.Create<MyPage, string>(p => p.UWPIcon, "");
    
            public string UWPIcon
            {
                get { return this.GetValue<string>(UWPIconProperty); }
                set { this.SetValue(UWPIconProperty, value); }
            }
    

    Now, in the UWP project, create a class that inherits from TabbedPageRenderer (note there is extra code here that you probably don't need but I was too lazy to edit out):

    [assembly: ExportRenderer(typeof(TabbedPage), typeof(TabbedPageCustom))]
    namespace MyProject.UWP.CustomRenderers
    {
        public class TabbedPageCustom : TabbedPageRenderer
        {
            string tabBarBackgroundColor = "#FF333333";
            string tabBarTextColor = "#FFFFFF";
            Windows.UI.Xaml.Controls.Pivot pivot;
            byte a, r, g, b;
            public TabbedPageCustom()
            {
                a = byte.Parse(tabBarBackgroundColor.Substring(1, 2), NumberStyles.HexNumber);
                r = byte.Parse(tabBarBackgroundColor.Substring(3, 2), NumberStyles.HexNumber);
                g = byte.Parse(tabBarBackgroundColor.Substring(5, 2), NumberStyles.HexNumber);
                b = byte.Parse(tabBarBackgroundColor.Substring(7, 2), NumberStyles.HexNumber);
            }
    
            protected override void OnElementChanged(VisualElementChangedEventArgs e)
            {
                base.OnElementChanged(e);
    
                var element = Element as TabbedPage;
                if (Control != null && element != null)
                {
                    Control.ToolbarBackground = new SolidColorBrush(Windows.UI.Color.FromArgb(a, r, g, b));
                    Control.HeaderTemplate = GetStyledHeaderTemplate(element); // here is where the icons are added
                    Control.Loaded += Control_Loaded;
                }
    
                if (e.OldElement == null) return;
    
                // Unhook when disposing control
                if (Control != null) Control.Loaded -= Control_Loaded;
    
            }
    
            private void Control_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
            {
                FormsPivot pivot = (FormsPivot) sender;
            }
    
            private void Control_SelectionChanged(object sender, Windows.UI.Xaml.Controls.SelectionChangedEventArgs e)
            {
                if (pivot == null) return;
    
                try
                {
                    for (int i = 0; i < pivot.Items.Count; i++)
                    {
                        if (i == pivot.SelectedIndex)
                        {
                            Windows.UI.Xaml.Controls.PivotItem unselectedPivotItem = pivot.Items[i] as Windows.UI.Xaml.Controls.PivotItem;
                            (unselectedPivotItem.Header as Windows.UI.Xaml.Controls.StackPanel).Background = new SolidColorBrush(Windows.UI.Colors.Aqua);
    
                        }
                        else
                        {
                            Windows.UI.Xaml.Controls.PivotItem unselectedPivotItem = pivot.Items[i] as Windows.UI.Xaml.Controls.PivotItem;
                            (unselectedPivotItem.Header as Windows.UI.Xaml.Controls.StackPanel).Background = new SolidColorBrush(Windows.UI.Color.FromArgb(a, r, g, b));
                        }
                    }
                }
                catch (Exception) { }
    
            }
    
            private void Control_Loaded(object sender, RoutedEventArgs e)
            {
                // Disable UWP swipe gesture on tabbled page
                if (Control.ItemsPanelRoot != null)
                    Control.ItemsPanelRoot.ManipulationMode = Windows.UI.Xaml.Input.ManipulationModes.None;
            }
    
            // Here is where the icons are added (the BitmapIcon's UriSource property is bound to the UWPIcon
            private Windows.UI.Xaml.DataTemplate GetStyledHeaderTemplate(TabbedPage element)
            {
                StringBuilder sb = new StringBuilder();
    
                sb.Append("<DataTemplate xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"");
                sb.Append(" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">");
                sb.Append("<StackPanel Margin=\"0\" Padding=\"0\" Width=\"" + (MyProject.App.ScreenWidth / element.Children.Count) + "\" Background=\"#333333\" VerticalAlignment=\"Top\">");
    
                // icon that will appear in the tab:
                sb.Append("<BitmapIcon UriSource=\"{Binding UWPIcon}\" Width=\"25\" Height=\"25\" Margin=\"0\" />");
    
                // text that will appear below the icon:
                sb.Append("<TextBlock Padding=\"0\" Margin=\"0\"");
                sb.Append(" Text=\"{Binding Title}\"");
                sb.Append(" FontFamily=\"Segoe UI\"");
                sb.Append(" HorizontalAlignment=\"Center\"");
                sb.Append(" FontSize=\"11\" />");
    
                sb.Append("</StackPanel>");
                sb.Append("</DataTemplate>");
    
                return (Windows.UI.Xaml.DataTemplate)XamlReader.Load(sb.ToString());
            }
    
        }
    }
    

    And in your TabbedPage.xaml.cs file:

                var myPage = new MyPage()
                {
                    Title = App.GlobalStrings.MyPageTitle,
                    UWPIcon = "ms-appx:///images/myicon.png"
                };
    
                Device.OnPlatform(
                    Android: () => { myPage.Icon = "myicon.png" ; },
                    iOS: () => { myPage.Icon = "images/myicon.png";  }
                );
    
                Children.Add(myPage);
    
  • DerProgrammiererDerProgrammierer DEMember ✭✭✭
    edited December 2016

    @Sme awesome work, the icons are now visible on UWP! I appreciate it a lot, thank you :)

    By the way, in Xamarin.Forms 2.1 generic versions of Create() are removed. So you should replace this line of code in the ContentPages:

    public static readonly BindableProperty UWPIconProperty = BindableProperty.Create<MyPage, string>(p => p.UWPIcon, "");

    Instead, use this:

    public static readonly BindableProperty UWPIconProperty = BindableProperty.Create(nameof(UWPIcon), typeof(string), typeof(MyPage));

  • heli_shahheli_shah Member ✭✭

    Anyone got any solution of icons not visible on Xamarin.UWP?

Sign In or Register to comment.