dgellow
dgellow

Reputation: 842

UWP How to get a NavigationView inner shadow projected by the content pane?

Looking at the UWP navigation view documentation at https://learn.microsoft.com/en-us/windows/uwp/design/controls-and-patterns/navigationview, I see multiple examples where the NavigationView has an inner shadow on the right side, projected by the content frame (see images below).

Is there a way to reproduce this style? By trying the examples of NavigationView available in the documentation and project examples, I get something different, where the left pane is the one projecting a shadow on the right side (when the navigation view is open), which is the exact opposite.

enter image description here

enter image description here

enter image description here

Upvotes: 0

Views: 617

Answers (2)

Difegue
Difegue

Reputation: 1

If you're using the WinUI NavigationView control, you can also hack around it to add the required ThemeShadows where necessary, but it's a bit more involved if you also want to keep the stock shadow behavior in Overlay mode:

Page.xaml

<NavigationView x:Name="NavigationView" Loaded="ApplyShadowToSideBar">
   <!-- Your navView content --> 
   <Grid>
         <Grid.Shadow>
              <ThemeShadow x:Name="ContentShadow" />
         </Grid.Shadow>
   </Grid>
</NavigationView>

Page.xaml.cs:

private void ApplyShadowToSideBar(object sender, RoutedEventArgs e)
{
    // Some VisualTree hacking to get the content grid for left display mode and cast shadows over it
    // Names of the ControlTemplates taken from https://github.com/microsoft/microsoft-ui-xaml/blob/master/dev/NavigationView/docs/rendering.md#displaymode-left
    Grid rootGrid = VisualTreeHelper.GetChild(NavigationView, 0) as Grid;
    if (rootGrid != null)
    {
        // Get the pane's grid, which receives all our shadows
        var paneContentGrid = rootGrid.FindName("PaneContentGrid") as Grid;

        // Shadow emitters for the header. The header has grids for both its content and top padding, so we need to shadow up both of them.
        var headerContent = rootGrid.FindName("HeaderContent") as ContentControl;
        var headerTopContent = rootGrid.FindName("ContentTopPadding") as Grid;
        var headerShadow = new ThemeShadow();
        var headerTopShadow = new ThemeShadow();

        // Remove default HeaderContent margin so the shadow can be cast correctly.
        // You can set NavigationViewHeaderMargin again in your own content to match.
        headerContent.Margin = new Thickness(0);

        // Set receivers
        headerShadow.Receivers.Add(paneContentGrid);
        headerTopShadow.Receivers.Add(paneContentGrid);
        ContentShadow.Receivers.Add(paneContentGrid);

        headerContent.Shadow = headerShadow;
        headerContent.Translation += new Vector3(0, 0, 32);

        headerTopContent.Shadow = headerTopShadow;
        headerTopContent.Translation += new Vector3(0, 0, 32);

        shellFrame.Translation += new Vector3(0, 0, 32);
    }
}

If you're using a Header for the NavigationView, you'll have to add a margin to it manually, and make sure to remove said margin when the NavView is in Minimal mode so you don't get extra whitespace.

Upvotes: 0

Nguyen Kien
Nguyen Kien

Reputation: 1927

It's now possible https://learn.microsoft.com/en-us/windows/uwp/design/layout/depth-shadow

<Grid>
   <Grid x:Name="Sidebar" Background="{ThemeResource SystemControlAcrylicWindowBrush}" />

   <Frame x:Name="Frame" Translation="0,0,10">
      <Windows10version1903:Frame.Shadow>
          <ThemeShadow x:Name="Shadow"/>
      </Windows10version1903:Frame.Shadow>
   </Frame>
</Grid>
Shadow.Receivers.Add(Sidebar);

Upvotes: 1

Related Questions