UWP - Prevent NavigationViewItemHeader from being clipped
Asked Answered
S

2

3

I am writing a UWP app that has a NavigationView containing NavigationViewItemHeaders:

   <NavigationView.MenuItems>
        <NavigationViewItem Content="Home" Tag="home">
            <NavigationViewItem.Icon>
                <FontIcon Glyph="&#xE80F;"/>
            </NavigationViewItem.Icon>
        </NavigationViewItem>

        <NavigationViewItemSeparator/>
        <NavigationViewItemHeader x:Name="ThemesHeading" Content="Themes"/>

        <NavigationViewItem Content="Themes" Tag="themes">
            <NavigationViewItem.Icon>
                <FontIcon Glyph="&#xE771;"/>
            </NavigationViewItem.Icon>
        </NavigationViewItem>

(and so on)

However when I collapse the view, the headers get clipped:

What should I do to prevent this?

Shorthand answered 23/12, 2017 at 20:33 Comment(0)
M
10

Solution 1

Increase the left margin of item headers:

<NavigationViewItemHeader Content="Themes" Margin="33,0,0,0"/>
...
<NavigationViewItemHeader Content="Builds" Margin="33,0,0,0"/>

enter image description here

Solution 2

Disable compact and expanded display mode of the NavigationView by setting the CompactModeThresholdWidth and ExpandedModeThresholdWidth to some big number:

<NavigationView CompactModeThresholdWidth="100000" ExpandedModeThresholdWidth="100000">

enter image description here

Solution 3

Bind the Visibility property of item headers to the IsPaneOpen property of the NavigationView as André B suggested, only use x:Bind instead of Binding since it doesn't need a converter:

<NavigationView Name="MyNavigationView">
    ...
            <NavigationViewItemHeader Content="Themes" Visibility="{x:Bind MyNavigationView.IsPaneOpen, Mode=OneWay}"/>
    ...
            <NavigationViewItemHeader Content="Builds" Visibility="{x:Bind MyNavigationView.IsPaneOpen, Mode=OneWay}"/>
    ...
</NavigationView>

enter image description here

Metathesis answered 24/12, 2017 at 2:40 Comment(1)
Also prevents false header showing when window width at minimum. CompactModeThresholdWidth="1" AlwaysShowHeader="False"Crankcase
W
0

Define the name attribute, x:Name, of your NavigationView object, so you can access to its IsPaneOpen property. Use the Binding property ElementName, to get the element you want to use as your binding Source, with the uniquely identifier that you defined with the attribute.

The IsPaneOpen property as the name suggests identifies whether the Pane is opened to it's full width, which can be used to toggle the Visibility of your NavigationViewItemHeader.Visibility property!

<NavigationView x:Name="NavView" ... >

    <NavigationViewItemHeader x:Name="ThemesHeading" Content="Themes" 
            Visibility="{Binding IsPaneOpen, 
                        ElementName=NavView, 
                        Converter={StaticResource BoolToVis}}"/>

</NavigationView>

Since the IsPaneOpen property returns a Boolean value, while Visibility is of type Enum, you need to create a Converter, so your Boolean state can be assigned to a value which makes sense to the Visibility Property. For our situation, we want :

NavigationView.IsPaneOpen = True -> NavigationViewItemHeader.Visibility = Visibility.Visible;

NavigationView.IsPaneOpen = False -> NavigationViewItemHeader.Visibility = Visibility.Collapsed;

By default Binding's Mode is set to OneWay, which is exactly what you want, since your NavigationView is the one who is going to dictate the visual state of the NavigationViewItemHeader, and you don't need the other way around.

Create a class, which is going to be your Converter! Your class has to inherit from IValueConverter interface. In my case, I created a folder called "Converter" and defined the BooleanToVisibilityConverter there.

namespace MyUWPApplication.Converter
{
    class BooleanToVisibilityConverter : IValueConverter
    {
        public BooleanToVisibilityConverter()
        {
        }

        public object Convert(object value, Type targetType, object parameter, string language)
        {
            if (value is bool && (bool)value)
            {
                return Visibility.Visible;
            }
            return Visibility.Collapsed;
        }

        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            throw new NotImplementedException();
        }
    }
}

In your XAML's page include the Namespace above (yours is going to be different), like this:

xmlns:common="using:MyUWPApplication.Converter"

Bellow, define your Converter's resource and give it a key, so you can reference it in the Binding definition.

            <Page.Resources>
                <common:BooleanToVisibilityConverter x:Key="BoolToVis" />
            </Page.Resources>

The converter resource BoolToVis, is being referenced in the Binding definition, and whenever there's a change to the IsPaneOpen property, the Convert function is going to be called to convert our Boolean value to Visibility.

Result:

enter image description here

Whereabouts answered 23/12, 2017 at 23:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.