microsoft / microsoft/microsoft-ui-xaml

Proposal: Right align NavigationView

Open
#10,441 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

area-NavigationView feature proposal
Dominant language
C++
Stars
8.4k
Forks
942
Avg merge
2d 7h
Merged PRs (30d)
105

Description

Would be nice to have a right-align NavigationView. Currently I achieve it with this:

```






<Setter Property="PaneToggleButtonStyle" Value="{StaticResource PaneToggleButtonStyle}" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="CompactPaneLength" Value="{ThemeResource NavigationViewCompactPaneLength}" />
<Setter Property="CornerRadius" Value="{ThemeResource OverlayCornerRadius}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:NavigationView">
<Grid x:Name="RootGrid">

<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="DisplayModeGroup">
<VisualState x:Name="Compact" />
<VisualState x:Name="Expanded" />
<VisualState x:Name="Minimal">
<VisualState.Setters>
<Setter Target="HeaderContent.Margin" Value="{ThemeResource NavigationViewMinimalHeaderMargin}" />
<Setter Target="NavigationViewBackButton.Style" Value="{ThemeResource NavigationBackButtonSmallStyle}" />
<Setter Target="ContentGrid.BorderThickness" Value="{ThemeResource NavigationViewMinimalContentGridBorderThickness}" />
<Setter Target="ContentGrid.CornerRadius" Value="{ThemeResource NavigationViewMinimalContentGridCornerRadius}" />
<Setter Target="ContentGrid.Margin" Value="{ThemeResource NavigationViewMinimalContentMargin}" />

</VisualState.Setters>
</VisualState>
<VisualState x:Name="TopNavigationMinimal">
<VisualState.Setters>
<Setter Target="ContentGrid.BorderThickness" Value="{ThemeResource TopNavigationViewContentGridBorderThickness}" />
<Setter Target="ContentGrid.CornerRadius" Value="{ThemeResource TopNavigationViewContentGridCornerRadius}" />
<Setter Target="ContentGrid.Margin" Value="{ThemeResource TopNavigationViewContentMargin}" />

</VisualState.Setters>
</VisualState>
<VisualState x:Name="MinimalWithBackButton">
<VisualState.Setters>
<Setter Target="HeaderContent.Margin" Value="{ThemeResource NavigationViewMinimalHeaderMargin}" />
<Setter Target="NavigationViewBackButton.Style" Value="{ThemeResource NavigationBackButtonSmallStyle}" />
<Setter Target="ContentGrid.BorderThickness" Value="{ThemeResource NavigationViewMinimalContentGridBorderThickness}" />
<Setter Target="ContentGrid.CornerRadius" Value="{ThemeResource NavigationViewMinimalContentGridCornerRadius}" />
<Setter Target="ContentGrid.Margin" Value="{ThemeResource NavigationViewMinimalContentMargin}" />

</VisualState.Setters>
</VisualState>

</VisualStateGroup>
<VisualStateGroup x:Name="TogglePaneGroup">
<VisualState x:Name="TogglePaneButtonCollapsed" />
<VisualState x:Name="TogglePaneButtonVisible">
<VisualState.Setters>
<Setter Target="PaneContentGridToggleButtonRow.MinHeight" Value="{StaticResource NavigationViewPaneHeaderRowMinHeight}" />
<Setter Target="PaneTitlePresenter.Margin" Value="{ThemeResource NavigationViewItemInnerHeaderMargin}" />

</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="AutoSuggestGroup">
<VisualState x:Name="AutoSuggestBoxVisible" />
<VisualState x:Name="AutoSuggestBoxCollapsed">
<VisualState.Setters>
<Setter Target="AutoSuggestArea.Visibility" Value="Collapsed" />
<Setter Target="TopPaneAutoSuggestArea.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="PaneStateListSizeGroup">
<VisualState x:Name="ListSizeFull" />
<VisualState x:Name="ListSizeCompact">
<VisualState.Setters>
<Setter Target="PaneContentGrid.Width" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=CompactPaneLength}" />
<Setter Target="ShadowCaster.Width" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=CompactPaneLength}" />
<Setter Target="PaneTitleTextBlock.Visibility" Value="Collapsed" />
<Setter Target="PaneHeaderContentBorder.Visibility" Value="Collapsed" />
<Setter Target="PaneCustomContentBorder.HorizontalAlignment" Value="Left" />
<Setter Target="FooterContentBorder.HorizontalAlignment" Value="Left" />

</VisualState.Setters>
</VisualState>

</VisualStateGroup>
<VisualStateGroup x:Name="PaneOverlayGroup">

<VisualStateGroup.Transitions>
<VisualTransition From="PaneNotOverlaying" To="PaneOverlaying">

<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ShadowCasterTransform" Storyboard.TargetProperty="TranslateX">
<DiscreteDoubleKeyFrame KeyTime="0" Value="{Binding ElementName=RootSplitView, Path=TemplateSettings.NegativeOpenPaneLengthMinusCompactLength}" />
<SplineDoubleKeyFrame KeyTime="0:0:0.35" KeySpline="0.1,0.9 0.2,1.0" Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ShadowCaster" Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="0:0:0.35" Value="1" />
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ShadowCaster" Storyboard.TargetProperty="HorizontalAlignment">
<DiscreteObjectKeyFrame KeyTime="0" Value="Left" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualTransition>
<VisualTransition From="PaneOverlaying" To="PaneNotOverlaying">
<Storyboard x:Name="ShadowCasterEaseOutStoryboard">
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ShadowCasterTransform" Storyboard.TargetProperty="TranslateX">
<DiscreteDoubleKeyFrame KeyTime="0" Value="0" />
<SplineDoubleKeyFrame KeyTime="0:0:0.12" KeySpline="0.1,0.9 0.2,1.0" Value="{Binding ElementName=RootSplitView, Path=TemplateSettings.NegativeOpenPaneLengthMinusCompactLength}" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ShadowCaster" Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="0:0:0.12" Value="0" />
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ShadowCaster" Storyboard.TargetProperty="HorizontalAlignment">
<DiscreteObjectKeyFrame KeyTime="0" Value="Left" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="PaneOverlaying" />
<VisualState x:Name="PaneNotOverlaying">
<VisualState.Setters>
<Setter Target="RootSplitView.BorderBrush" Value="Transparent" />
<Setter Target="ShadowCaster.Opacity" Value="0" />
<Setter Target="RootSplitView.PaneBackground" Value="{ThemeResource NavigationViewExpandedPaneBackground}" />

</VisualState.Setters>
</VisualState>

</VisualStateGroup>
<VisualStateGroup x:Name="TitleBarVisibilityGroup">
<VisualState x:Name="TitleBarVisible" />
<VisualState x:Name="TitleBarCollapsed">
<VisualState.Setters>
<Setter Target="PaneContentGrid.Margin" Value="0,32,0,0" />

</VisualState.Setters>
</VisualState>

</VisualStateGroup>
<VisualStateGroup x:Name="OverflowLabelGroup">
<VisualState x:Name="OverflowButtonWithLabel" />
<VisualState x:Name="OverflowButtonNoLabel">
<VisualState.Setters>
<Setter Target="TopNavOverflowButton.Style" Value="{ThemeResource NavigationViewOverflowButtonNoLabelStyleWhenPaneOnTop}" />

</VisualState.Setters>
</VisualState>

</VisualStateGroup>
<VisualStateGroup x:Name="BackButtonGroup">
<VisualState x:Name="BackButtonVisible" />
<VisualState x:Name="BackButtonCollapsed">
<VisualState.Setters>
<Setter Target="BackButtonPlaceholderOnTopNav.Width" Value="0" />

</VisualState.Setters>
</VisualState>

</VisualStateGroup>
<VisualStateGroup x:Name="PaneVisibilityGroup">
<VisualState x:Name="PaneVisible" />
<VisualState x:Name="PaneCollapsed">
<VisualState.Setters>
<Setter Target="RootSplitView.CompactPaneLength" Value="0" />
<Setter Target="ShadowCaster.Width" Value="0" />
<Setter Target="PaneToggleButtonGrid.Visibility" Value="Collapsed" />

</VisualState.Setters>
</VisualState>

</VisualStateGroup>
<VisualStateGroup x:Name="PaneSeparatorStates">
<VisualState x:Name="SeparatorCollapsed" />
<VisualState x:Name="SeparatorVisible">
<VisualState.Setters>
<Setter Target="VisualItemsSeparator.Visibility" Value="Visible" />

</VisualState.Setters>
</VisualState>

</VisualStateGroup>

</VisualStateManager.VisualStateGroups>
<Grid x:Name="PaneToggleButtonGrid" HorizontalAlignment="Right" VerticalAlignment="Top" Canvas.ZIndex="100">

<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid x:Name="TogglePaneTopPadding" Height="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.TopPadding}" />
<Grid x:Name="ButtonHolderGrid" Grid.Row="1" Margin="{ThemeResource NavigationViewButtonHolderGridMargin}">
<Button x:Name="NavigationViewBackButton" Style="{StaticResource NavigationBackButtonNormalStyle}" Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.SmallerPaneToggleButtonWidth}" VerticalAlignment="Top" Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.BackButtonVisibility}" IsEnabled="{TemplateBinding IsBackEnabled}">
<ToolTipService.ToolTip>
<ToolTip x:Name="NavigationViewBackButtonToolTip" />
</ToolTipService.ToolTip>
</Button>
<Button x:Name="NavigationViewCloseButton" Style="{StaticResource NavigationBackButtonNormalStyle}" VerticalAlignment="Top">
<ToolTipService.ToolTip>
<ToolTip x:Name="NavigationViewCloseButtonToolTip" />
</ToolTipService.ToolTip>
</Button>
<Button x:Name="TogglePaneButton" Style="{TemplateBinding PaneToggleButtonStyle}" AutomationProperties.LandmarkType="Navigation" HorizontalAlignment="Center" Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.PaneToggleButtonVisibility}" VerticalAlignment="Top" MinWidth="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.SmallerPaneToggleButtonWidth}" FocusVisualMargin="0">
<TextBlock x:Name="PaneTitleTextBlock" Grid.Column="0" Margin="0,-2,0,0" Text="{TemplateBinding PaneTitle}" HorizontalAlignment="Left" VerticalAlignment="Center" Style="{StaticResource NavigationViewItemHeaderTextStyle}" />
</Button>
<Grid x:Name="PaneTitleHolder" Height="40" Visibility="Collapsed">
<ContentControl x:Name="PaneTitlePresenter" Margin="{ThemeResource NavigationViewPaneTitlePresenterMargin}" IsTabStop="False" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" />

</Grid>
</Grid>

</Grid>

<Grid>

<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel x:Name="TopNavArea" Background="{ThemeResource NavigationViewTopPaneBackground}" Grid.Row="0" HorizontalAlignment="Stretch" VerticalAlignment="Top" Canvas.ZIndex="1" XYFocusKeyboardNavigation="Enabled">
<Grid x:Name="TopNavTopPadding" Height="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.TopPadding}" Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.TopPaneVisibility}" />
<Grid x:Name="TopNavGrid" Height="{ThemeResource NavigationViewTopPaneHeight}" Margin="{ThemeResource TopNavigationViewTopNavGridMargin}" Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.TopPaneVisibility}" BorderBrush="{ThemeResource NavigationViewItemSeparatorForeground}">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="BackButtonPlaceholderOnTopNav" Width="{ThemeResource NavigationBackButtonWidth}" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" MinWidth="{ThemeResource TopNavigationViewPaneCustomContentMinWidth}" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid x:Name="TopNavLeftPadding" Grid.Column="1" Width="0" />
<ContentControl x:Name="PaneHeaderOnTopPane" IsTabStop="False" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" Grid.Column="2" />
<ContentControl x:Name="PaneTitleOnTopPane" IsTabStop="False" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" Margin="{ThemeResource NavigationViewItemInnerHeaderMargin}" Grid.Column="2" />
<controls:ItemsRepeaterScrollHost Grid.Column="3">
<ScrollViewer HorizontalScrollMode="Disabled" HorizontalScrollBarVisibility="Hidden" VerticalScrollMode="Disabled" VerticalScrollBarVisibility="Hidden">
<controls:ItemsRepeater AutomationProperties.LandmarkType="Navigation" AutomationProperties.Name="{TemplateBinding AutomationProperties.Name}" AutomationProperties.AccessibilityView="Content" x:Name="TopNavMenuItemsHost">
<controls:ItemsRepeater.Layout>
<controls:StackLayout Orientation="Horizontal" />
</controls:ItemsRepeater.Layout>
</controls:ItemsRepeater>
</ScrollViewer>
</controls:ItemsRepeaterScrollHost>
<Button x:Name="TopNavOverflowButton" Grid.Column="4" Content="More" Margin="{ThemeResource TopNavigationViewOverflowButtonMargin}" Style="{StaticResource NavigationViewOverflowButtonStyleWhenPaneOnTop}" Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.OverflowButtonVisibility}">
<Button.Flyout>
<Flyout Placement="BottomEdgeAlignedRight" ElementSoundMode="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ElementSoundMode}">
<Flyout.FlyoutPresenterStyle>
<Style TargetType="FlyoutPresenter">
<Setter Property="Padding" Value="{ThemeResource TopNavigationViewOverflowMenuPadding}" />
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Auto" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" />
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Auto" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
<Setter Property="ScrollViewer.ZoomMode" Value="Disabled" />
<Setter Property="CornerRadius" Value="{ThemeResource OverlayCornerRadius}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="FlyoutPresenter">
<ScrollViewer x:Name="ScrollViewer"
ZoomMode="{TemplateBinding ScrollViewer.ZoomMode}"
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
AutomationProperties.AccessibilityView="Raw">
<ContentPresenter x:Name="ContentPresenter" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" ContentTransitions="{TemplateBinding ContentTransitions}" Padding="{TemplateBinding Padding}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" CornerRadius="{TemplateBinding CornerRadius}" />
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>













































































































































```

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing the existing NavigationView implementation and its control template, using the custom template in the issue body as a reference for current alignment behavior. Determine the supported scope for right alignment across NavigationView modes and define completion around a consistent built-in right-aligned result without the workaround shown.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
desktop
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
32/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.