You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置随菜单开闭伸缩的全局可见Horizontal StackPanel?

实现随NavigationView菜单伸缩的全局头部StackPanel

要让全局头部始终可见且随菜单伸缩,关键是让头部与NavigationView的面板宽度联动,而非独立于NavigationView布局。以下是修改后的实现方案:

修改后的完整XAML代码

<Page
    x:Class="Application.Views.ShellPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:helpers="using:Application.Helpers"
    xmlns:behaviors="using:Application.Behaviors"
    xmlns:i="using:Microsoft.Xaml.Interactivity"
    Loaded="OnLoaded">

    <Grid>
        <!-- 保留原窗口标题栏 -->
        <Grid x:Name="AppTitleBar"
              Canvas.ZIndex="1"
              Height="{Binding ElementName=NavigationViewControl, Path=CompactPaneLength}"
              IsHitTestVisible="True"
              VerticalAlignment="Top">
            <Image Source="/Assets/WindowIcon.ico"
                   HorizontalAlignment="Left"
                   Width="16"
                   Height="16" />
            <TextBlock x:Name="AppTitleBarText"
                       VerticalAlignment="Center"
                       TextWrapping="NoWrap"
                       Style="{StaticResource CaptionTextBlockStyle}"
                       Margin="28,0,0,0"/>
        </Grid>

        <NavigationView
            x:Name="NavigationViewControl"
            Canvas.ZIndex="0"
            IsBackButtonVisible="Visible"
            IsBackEnabled="{x:Bind ViewModel.IsBackEnabled, Mode=OneWay}"
            SelectedItem="{x:Bind ViewModel.Selected, Mode=OneWay}"
            IsSettingsVisible="True"
            ExpandedModeThresholdWidth="1280"
            DisplayModeChanged="NavigationViewControl_DisplayModeChanged"
            Header="{x:Bind ((ContentControl)ViewModel.Selected).Content, Mode=OneWay}">
            <NavigationView.MenuItems>
                    <!-- 保留原菜单内容 -->
            </NavigationView.MenuItems>
            <NavigationView.HeaderTemplate>
                <DataTemplate>
                    <Grid>
                        <TextBlock
                            Text="{Binding}"
                            Style="{ThemeResource TitleTextBlockStyle}" />
                    </Grid>
                </DataTemplate>
            </NavigationView.HeaderTemplate>
            <i:Interaction.Behaviors>
                <behaviors:NavigationViewHeaderBehavior
                    DefaultHeader="{x:Bind ((ContentControl)ViewModel.Selected).Content, Mode=OneWay}">
                    <behaviors:NavigationViewHeaderBehavior.DefaultHeaderTemplate>
                        <DataTemplate>
                            <Grid>
                                <TextBlock
                                    Text="{Binding}"
                                    Style="{ThemeResource TitleTextBlockStyle}" />
                            </Grid>
                        </DataTemplate>
                    </behaviors:NavigationViewHeaderBehavior.DefaultHeaderTemplate>
                </behaviors:NavigationViewHeaderBehavior>
            </i:Interaction.Behaviors>

            <!-- 重新布局Content区域:先放全局头部,再放页面Frame -->
            <StackPanel Orientation="Vertical">
                <!-- 全局统一头部StackPanel -->
                <StackPanel x:Name="GlobalHeader" 
                            Orientation="Horizontal"
                            Background="{ThemeResource SystemControlAcrylicWindowBrush}"
                            Height="60"
                            VerticalAlignment="Top"
                            Padding="16,0">
                    <!-- 头部内容示例:可替换为你的自定义控件 -->
                    <TextBlock Text="全局统一头部" 
                               Style="{ThemeResource TitleTextBlockStyle}" 
                               VerticalAlignment="Center"/>
                    <Button Content="功能按钮" 
                            Margin="24,0"
                            VerticalAlignment="Center"/>
                </StackPanel>

                <!-- 页面内容区域 -->
                <Grid Margin="{StaticResource NavigationViewPageContentMargin}"
                      VerticalAlignment="Stretch">
                    <Frame x:Name="NavigationFrame" />
                </Grid>
            </StackPanel>
        </NavigationView>
    </Grid>
</Page>

关键实现细节

  1. 布局嵌套:将全局头部放在NavigationView的Content内部,与页面Frame处于同一垂直StackPanel中,确保头部始终在页面内容上方,切换页面时不会消失。
  2. 菜单联动逻辑:在NavigationViewControl_DisplayModeChanged事件中手动设置头部的左边距,适配菜单展开/收起状态:
private void NavigationViewControl_DisplayModeChanged(NavigationView sender, NavigationViewDisplayModeChangedEventArgs args)
{
    // 根据菜单显示模式设置头部左边距
    double leftPadding = sender.DisplayMode switch
    {
        NavigationViewDisplayMode.Expanded => sender.ExpandedPaneLength,
        NavigationViewDisplayMode.Minimal => 0,
        _ => sender.CompactPaneLength
    };
    GlobalHeader.Margin = new Thickness(leftPadding, 0, 0, 0);
}
  1. 样式适配:头部使用SystemControlAcrylicWindowBrush背景,保持与WinUI风格一致,高度和内边距可根据需求调整。

替代方案(使用绑定转换器)

如果不想通过事件处理,可自定义DoubleToThicknessConverter,直接绑定PaneActualWidth属性到头部的左边距:

public class DoubleToThicknessConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        double width = (double)value;
        return new Thickness(width, 0, 0, 0);
    }

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

在XAML中引用转换器后,头部的Margin可改为:

Margin="{Binding ElementName=NavigationViewControl, Path=PaneActualWidth, Converter={StaticResource DoubleToThicknessConverter}}"

内容的提问来源于stack exchange,提问作者mainhar2

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 13:55:01