Ovladací prvek NavigationView
který byl přidán v aktualizaci Fall Creators Update pro Windows 10 je velmi užitečný nástroj pro vytváření uživatelsky přívětivé hamburger menu navigace, která zapadá do UX guidelines UWP aplikací. NavigationView
obsahuje prostor pro hlavičku, kam můžete vložit titulek vaší stránky aplikace. Co když však hlavičku nechceme zobrazovat?
Minimální problém
NavigationView
má vlastnost AlwaysShowHeader
, která nám umožňuje specifikovat, zda chceme hlavičku vždy zobrazovat nebo ne. Tato vlastnost se chová přesně jak potřebujeme až do té doby, kdy okno aplikace zmenšíme a NavigationView
se přepne do módu Minimal
.
Ikdyž je hlavička prázdná, náš obsah je posunut dolů, aby pro ni vytvořil místo. To není úplně uživatelsky přívětivé, především na malých displejích (jako telefonních), kde se každý pixel počítá.
Skrytý v šabloně
Když se zahloubáme do výchozího stylu NavigationView
, můžeme zde najít následující XAML definici:
<ContentControl x:Name="HeaderContent" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" HorizontalContentAlignment="Stretch" IsTabStop="False" MinHeight="48" VerticalContentAlignment="Stretch"/>
Problém je poměrně zřejmý - vlastnost MinHeight
hlavičky je nastavena na 48 efektivních pixelů. V módu Minimal
je header vždy zobrazen a i v případě že nic neobsahuje, zabírá cenných 48 pixelů z výšky vaší aplikace. Řešení je velmi snadné – můžeme vlastnost MinHeight
prostě odstranit.
S tímto řešením je hlavička "neviditelná", ale pokud do ni vložíme nějaký obsah, znovu ji můžeme snadno zobrazit. Samozřejme si musíme nyní dát pozor, že levý horní roh našeho obsahu může být zakryt tlačítkem pro otevření hamburger menu.Tento problém nástává pouze v módu Minimal
, takže lze použít VisualStateTrigger
a přidat požadované levé odsazení prvkům vaší stránky. Zde je zdrojový kód celého aktualizovaného Style
. Můžete je také najít ve zdrojovém kódu k tomuto článku na GitHubu.
<Style x:Key="CustomNavigationMenuStyle" TargetType="NavigationView"> <Setter Property="PaneToggleButtonStyle" Value="{StaticResource PaneToggleButtonStyle}"/> <Setter Property="IsTabStop" Value="False"/> <Setter Property="HeaderTemplate"> <Setter.Value> <DataTemplate> <Grid Margin="12,5,0,11" VerticalAlignment="Stretch"> <TextBlock x:Name="Header" Style="{StaticResource TitleTextBlockStyle}" Text="{Binding}" TextWrapping="NoWrap" VerticalAlignment="Bottom"/> </Grid> </DataTemplate> </Setter.Value> </Setter> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="NavigationView"> <Grid x:Name="RootGrid"> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="DisplayModeGroup"> <VisualState x:Name="Compact"/> <VisualState x:Name="Expanded"> <VisualState.Setters> <Setter Target="RootSplitView.PaneBackground" Value="{ThemeResource NavigationViewExpandedPaneBackground}"/> </VisualState.Setters> </VisualState> <VisualState x:Name="Minimal"> <VisualState.Setters> <Setter Target="HeaderContent.Margin" Value="48,0,0,0"/> </VisualState.Setters> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="TogglePaneGroup"> <VisualState x:Name="TogglePaneButtonVisible"/> <VisualState x:Name="TogglePaneButtonCollapsed"> <VisualState.Setters> <Setter Target="TogglePaneButton.Visibility" Value="Collapsed"/> <Setter Target="PaneContentGridToggleButtonRow.Height" Value="4"/> </VisualState.Setters> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="HeaderGroup"> <VisualState x:Name="HeaderVisible"/> <VisualState x:Name="HeaderCollapsed"> <VisualState.Setters> <Setter Target="HeaderContent.Visibility" Value="Collapsed"/> </VisualState.Setters> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="SettingsGroup"> <VisualState x:Name="SettingsVisible"/> <VisualState x:Name="SettingsCollapsed"> <VisualState.Setters> <Setter Target="SettingsNavPaneItem.Visibility" Value="Collapsed"/> </VisualState.Setters> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="AutoSuggestGroup"> <VisualState x:Name="AutoSuggestBoxVisible"/> <VisualState x:Name="AutoSuggestBoxCollapsed"> <VisualState.Setters> <Setter Target="AutoSuggestArea.Visibility" Value="Collapsed"/> </VisualState.Setters> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="PaneStateGroup"> <VisualState x:Name="NotClosedCompact"/> <VisualState x:Name="ClosedCompact"> <VisualState.Setters> <Setter Target="PaneAutoSuggestBoxPresenter.Visibility" Value="Collapsed"/> <Setter Target="PaneAutoSuggestButton.Visibility" Value="Visible"/> </VisualState.Setters> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="TitleBarVisibilityGroup"> <VisualState x:Name="TitleBarVisible"/> <VisualState x:Name="TitleBarCollapsed"> <VisualState.Setters> <Setter Target="PaneButtonGrid.Margin" Value="0,32,0,0"/> <Setter Target="PaneContentGrid.Margin" Value="0,32,0,0"/> </VisualState.Setters> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <Grid HorizontalAlignment="Left" Margin="0,0,0,8" VerticalAlignment="Top" Width="{StaticResource PaneToggleButtonSize}" Canvas.ZIndex="100"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid x:Name="TogglePaneTopPadding"/> <Button x:Name="TogglePaneButton" AutomationProperties.LandmarkType="Navigation" Grid.Row="1" Style="{TemplateBinding PaneToggleButtonStyle}"/> </Grid> <SplitView x:Name="RootSplitView" Background="{TemplateBinding Background}" CompactPaneLength="{TemplateBinding CompactPaneLength}" DisplayMode="Inline" IsTabStop="False" IsPaneOpen="{Binding IsPaneOpen, Mode=TwoWay, RelativeSource={RelativeSource Mode=TemplatedParent}}" OpenPaneLength="{TemplateBinding OpenPaneLength}" PaneBackground="{ThemeResource NavigationViewDefaultPaneBackground}"> <SplitView.Pane> <Grid x:Name="PaneContentGrid"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition x:Name="PaneContentGridToggleButtonRow" Height="56"/> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="8"/> </Grid.RowDefinitions> <Grid x:Name="ContentPaneTopPadding"/> <Grid x:Name="AutoSuggestArea" Height="40" Grid.Row="2" VerticalAlignment="Center"> <ContentControl x:Name="PaneAutoSuggestBoxPresenter" Content="{TemplateBinding AutoSuggestBox}" HorizontalContentAlignment="Stretch" IsTabStop="False" Margin="12,0,12,0" VerticalContentAlignment="Center"/> <Button x:Name="PaneAutoSuggestButton" Content="" MinHeight="40" Style="{TemplateBinding PaneToggleButtonStyle}" Visibility="Collapsed" Width="{TemplateBinding CompactPaneLength}"/> </Grid> <NavigationViewList x:Name="MenuItemsHost" ItemContainerStyleSelector="{TemplateBinding MenuItemContainerStyleSelector}" ItemContainerStyle="{TemplateBinding MenuItemContainerStyle}" ItemTemplate="{TemplateBinding MenuItemTemplate}" IsItemClickEnabled="True" ItemsSource="{TemplateBinding MenuItemsSource}" ItemTemplateSelector="{TemplateBinding MenuItemTemplateSelector}" Margin="0,0,0,20" Grid.Row="3" SelectionMode="Single" SelectedItem="{TemplateBinding SelectedItem}"/> <Border x:Name="FooterContentBorder" Child="{TemplateBinding PaneFooter}" Grid.Row="4"/> <NavigationViewItem x:Name="SettingsNavPaneItem" Grid.Row="5"> <NavigationViewItem.Icon> <SymbolIcon Symbol="Setting"/> </NavigationViewItem.Icon> </NavigationViewItem> </Grid> </SplitView.Pane> <Grid x:Name="ContentGrid"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <ContentControl x:Name="HeaderContent" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" HorizontalContentAlignment="Stretch" IsTabStop="False" VerticalContentAlignment="Stretch"/> <ContentPresenter Content="{TemplateBinding Content}" Grid.Row="1"/> </Grid> </SplitView> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>
Ukázkový kód
Zdrojový kód k tomuto článku je k dispozici na mém GitHubu.
Shrnutí
Ukázali jsme si jak vynutit v NavigationView
skrytí hlavičky i v módu Minimal
aby obsah naší aplikace byl úplně bez hranic.