Search code examples
c#xamluwpwin-universal-app

UWP NavigationView and TabView collision


As you can see from the top of the image, the hamburger button of the NavigationView overlaps with my TabView.TabStartHeader. The TabView is in a Frame of MainPage while NavigationView is in the MainPage.

Now I want them aligned horizontally with the hamburger button on the left and the Add button on the right. How can I achieve that?

enter image description here

XAML of MainPage: https://github.com/SeakyLuo/SMPlayer/blob/master/SMPlayer/MainPage.xaml

XAML of TabView: https://github.com/SeakyLuo/SMPlayer/blob/master/SMPlayer/PlaylistsPage.xaml


Solution

  • The problem that you are facing is due to the default behavior of the NavigationView. Whenever the window size is reduced to a certain limit, PaneDisplayMode is changed to LeftMinimal to increase the viewable area . Thus the Frame which was previously sitting beside the navigation view is now directly below the navigation bar . Due to this, the "New Tab" button of the Tab View goes below the "hamburger Button" of the navigation bar .

    The highlighted selection shows the area covered by the Frame which has the page with the TabView

    enter image description here

    To prevent this from happening the easiest way would be to specify a single PaneDisplayMode for all screen sizes :

    <NavigationView
                x:Name="MainNavigationView"
                ........
                PaneDisplayMode="LeftCompact">
    

    A better approach would be to switch the PaneDisplayMode using VisualStateManager or Adaptive Triggers .

    For example you can have the PaneDisplayMode as 'Auto' for window size greater than ~700px (based on your preference) and for lower window sizes you can switch it to 'Top'/'Left Compact'.

    XAML Code

    <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="VisualStateGroup">
                <VisualState x:Name="VisualStateMin0">
                    <VisualState.Setters>
                        <Setter Target="MainNavigationView.(NavigationView.PaneDisplayMode)" Value="LeftCompact"/>
                    </VisualState.Setters>
                    <VisualState.StateTriggers>
                        <AdaptiveTrigger MinWindowWidth="1" MinWindowHeight="1"/>
                    </VisualState.StateTriggers>
                </VisualState>
                <VisualState x:Name="VisualStateMin700">
                    <VisualState.StateTriggers>
                        <AdaptiveTrigger MinWindowWidth="700" MinWindowHeight="1"/>
                    </VisualState.StateTriggers>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
    

    You should see a behavior like this :

    PaneDisplayMode - Top for small window size :

    enter image description here

    PaneDisplayMode - Left Compact for small window size :

    enter image description here


    Update after Seaky Luo's comment :

    Exact solution (though it does not look as natural as the other solutions):

    For this you will need to add left margin to the "New Tab" button when the window size is small and the NavigationView switches to LeftMinimal.

    I found that when the width is around ~640 the navigation view goes into LeftMinimal (you might have to fine tune that number).

    XAML Code : [To be added to the Page called within the frame (PlayListsPage.xaml in this case)]

    <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="VisualStateGroup">
                <VisualState x:Name="VisualStateMin0">
                    <VisualState.Setters>
                        <Setter Target="NewPlaylistButton.(FrameworkElement.Margin)">
                            <Setter.Value>
                                <Thickness>40,0,0,0</Thickness>
                            </Setter.Value>
                        </Setter>
                    </VisualState.Setters>
                    <VisualState.StateTriggers>
                        <AdaptiveTrigger MinWindowWidth="1" MinWindowHeight="1"/>
                    </VisualState.StateTriggers>
                </VisualState>
                <VisualState x:Name="VisualStateMin640">
                    <VisualState.StateTriggers>
                        <AdaptiveTrigger MinWindowWidth="640" MinWindowHeight="1"/>
                    </VisualState.StateTriggers>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
    

    It should look something like this :

    enter image description here

    Hope this helps !