首页 > 解决方案 > WPF子菜单覆盖而不是展开

问题描述

抱歉,我真的没有源代码,因为我不知道要使用什么元素。

我正在制作一个菜单导航控件。菜单将有两个级别。我希望选择菜单项时出现在右侧的子项目。但是,我希望他们覆盖那里的任何内容,而不仅仅是扩展。在图像中,基本上是我想在红色部分上方显示的子项目部分。现在它只会扩展左侧菜单栏区域。

我看过使用弹出控件,但它似乎有很多问题,比如窗口移动。它仍然是这样的最佳选择吗?

我也看过设置 zindex 但这似乎只适用于同一控制空间中的项目。

在此处输入图像描述

标签: c#wpfxaml

解决方案


我花了大约三天的时间才得到我想要设计的东西。弹出窗口有时很神秘,但它们可以为所欲为。

我认为它们的关键属性是 Placement、Horizo​​ntalOffset 和 VerticalOffset。通过以您想要显示的方式设置它们,您将看到它们的灵活性。

我使用 ControlTemplates 设计了自己的:

 <SolidColorBrush x:Key="MenuBackground" Color="#1A1A1A" />

 <!-- Menu: MainMenu Style-->
 <Style x:Key="{x:Type Menu}" TargetType="Menu">
     <Setter Property="FontFamily" Value="{StaticResource IranSans}"/>
     <Setter Property="OverridesDefaultStyle" Value="True"/>
     <Setter Property="SnapsToDevicePixels" Value="True"/>
     <Setter Property="Height" Value="28"/>
     <Setter Property="Template">
         <Setter.Value>
             <ControlTemplate TargetType="Menu">
                 <Border Background="{StaticResource MenuBackground}">
                     <StackPanel ClipToBounds="True" Background="{TemplateBinding Background}" Orientation="Horizontal" IsItemsHost="True"/>
                 </Border>
             </ControlTemplate>
         </Setter.Value>
     </Setter>
 </Style>

<!-- Fill Brushes -->
<LinearGradientBrush x:Key="NormalBrush" StartPoint="0,0" EndPoint="0,1">
    <GradientBrush.GradientStops>
        <GradientStopCollection>
            <GradientStop Color="#FFF" Offset="0.0"/>
            <GradientStop Color="#CCC" Offset="1.0"/>
        </GradientStopCollection>
    </GradientBrush.GradientStops>
</LinearGradientBrush>

<SolidColorBrush x:Key="DisabledForegroundBrush" Color="#888" />
<SolidColorBrush x:Key="DisabledBackgroundBrush" Color="#EEE" />
<SolidColorBrush x:Key="WindowBackgroundBrush" Color="#FFF" />
<SolidColorBrush x:Key="SelectedBackgroundBrush" Color="#DDD" />
<SolidColorBrush x:Key="MenuBackground" Color="#1A1A1A" />
<SolidColorBrush x:Key="EnabledForegroundBrush" Color="#CCC" />
<SolidColorBrush x:Key="MenuClick" Color="#4D4D4D" />
<SolidColorBrush x:Key="ItemHighlight" Color="#717171" />

<!-- Border Brushes -->
<LinearGradientBrush x:Key="NormalBorderBrush" StartPoint="0,0" EndPoint="0,1">
    <GradientBrush.GradientStops>
        <GradientStopCollection>
            <GradientStop Color="#CCC" Offset="0.0"/>
            <GradientStop Color="#444" Offset="1.0"/>
        </GradientStopCollection>
    </GradientBrush.GradientStops>
</LinearGradientBrush>
<LinearGradientBrush x:Key="HorizontalNormalBorderBrush" StartPoint="0,0" EndPoint="1,0">
    <GradientBrush.GradientStops>
        <GradientStopCollection>
            <GradientStop Color="#CCC" Offset="0.0"/>
            <GradientStop Color="#444" Offset="1.0"/>
        </GradientStopCollection>
    </GradientBrush.GradientStops>
</LinearGradientBrush>

<!-- Miscellaneous Brushes -->
<SolidColorBrush x:Key="GlyphBrush" Color="#444" />

<!--SeparatorStyleKey : Menu Separator Styles -->
<!-- [1] Separator Tag -->
<Style x:Key="{x:Static MenuItem.SeparatorStyleKey}" TargetType="Separator">
    <Setter Property="Height" Value="8"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Separator">
                <Border Background="{StaticResource MenuClick}" Height="{TemplateBinding Height}">
                    <Border VerticalAlignment="Center" BorderBrush="{StaticResource EnabledForegroundBrush}" BorderThickness="1"/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<!-- TopLevelHeader-->
<ControlTemplate x:Key="{x:Static MenuItem.TopLevelHeaderTemplateKey}" TargetType="MenuItem">
    <Border Name="Border" Background="{StaticResource MenuBackground}">
        <Grid VerticalAlignment="Center">
            <StackPanel Orientation="Horizontal">
                <ContentPresenter  Margin="6,3,3,3" VerticalAlignment="Center" ContentSource="Header" RecognizesAccessKey="True" />
                <TextBlock Margin="0 0 3 0" HorizontalAlignment="Center" VerticalAlignment="Center" Text="▾" FontSize="13"/>
            </StackPanel>
 <Popup Name="Popup" Placement="Bottom" VerticalOffset="2" HorizontalOffset="-8" IsOpen="{TemplateBinding IsSubmenuOpen}" AllowsTransparency="True" Focusable="False" PopupAnimation="Fade">
     <Border Padding="8 0 8 8">
         <Border Name="SubmenuBorder" SnapsToDevicePixels="True" Background="{StaticResource MenuClick}" BorderBrush="{StaticResource MenuClick}"  BorderThickness="5">
             <Border.Effect>
                 <DropShadowEffect ShadowDepth="0" Color="#AAA" Opacity="1" BlurRadius="10"/>
             </Border.Effect>
             <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Cycle" />
     </Border>
     </Border>
 </Popup>                                   
        </Grid>
    </Border>
    <ControlTemplate.Triggers>
        <Trigger Property="IsSuspendingPopupAnimation" Value="true">
            <Setter TargetName="Popup" Property="PopupAnimation" Value="None"/>
        </Trigger>
        <Trigger Property="IsHighlighted" Value="true">
            <Setter TargetName="Border" Property="Background" Value="{StaticResource ItemHighlight}"/>
            <Setter TargetName="Border" Property="BorderBrush" Value="Transparent"/>
        </Trigger>
        <Trigger Property="IsEnabled" Value="False">
            <Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/>
        </Trigger>
        <Trigger Property="IsEnabled" Value="True">
            <Setter Property="Foreground" Value="{StaticResource EnabledForegroundBrush}"/>
        </Trigger>
        <Trigger Property="IsPressed" Value="true">
            <Setter TargetName="Border" Property="Background" Value="{StaticResource MenuClick}"/>
        </Trigger>
        <Trigger Property="IsSubmenuOpen" Value="true">
            <Setter TargetName="Border" Property="Background" Value="{StaticResource MenuClick}"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

<!-- TopLevelItem -->
<ControlTemplate  x:Key="{x:Static MenuItem.TopLevelItemTemplateKey}" TargetType="MenuItem">
    <Border Name="Border" Background="{StaticResource MenuBackground}">
        <Grid>
            <ContentPresenter Margin="6,3,6,3" VerticalAlignment="Center" ContentSource="Header" RecognizesAccessKey="True" />
        </Grid>
    </Border>
    <ControlTemplate.Triggers>
        <Trigger Property="IsHighlighted" Value="true">
            <Setter TargetName="Border" Property="Background"  Value="{StaticResource ItemHighlight}"/>
            <Setter TargetName="Border" Property="BorderBrush" Value="Transparent"/>
        </Trigger>
        <Trigger Property="IsEnabled" Value="False">
            <Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/>
        </Trigger>
        <Trigger Property="IsEnabled" Value="True">
            <Setter Property="Foreground" Value="{StaticResource EnabledForegroundBrush}"/>
        </Trigger>
        <Trigger Property="IsPressed" Value="true">
            <Setter TargetName="Border" Property="Background" Value="{StaticResource MenuClick}"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

<!-- SubmenuItem -->
<ControlTemplate x:Key="{x:Static MenuItem.SubmenuItemTemplateKey}" TargetType="MenuItem">
    <Border Name="Border" Background="{StaticResource MenuClick}">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" SharedSizeGroup="Icon"/>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="Auto" SharedSizeGroup="Shortcut"/>
                <ColumnDefinition Width="13"/>
            </Grid.ColumnDefinitions>
            <ContentPresenter Name="Icon" Margin="3,3,9,3" Height="18" Width="18" VerticalAlignment="Center" ContentSource="Icon"/>
            <Border Name="Check" Width="13" Height="13" Visibility="Collapsed" Margin="6,0,6,0" Background="{StaticResource NormalBrush}" BorderThickness="1" BorderBrush="{StaticResource NormalBorderBrush}">
                <Path Name="CheckMark" Width="7" Height="7"  Visibility="Hidden" SnapsToDevicePixels="False" Stroke="{StaticResource GlyphBrush}" StrokeThickness="2" Data="M 0 0 L 7 7 M 0 7 L 7 0" />
            </Border>
            <ContentPresenter Name="HeaderHost" Grid.Column="1" VerticalAlignment="Center" ContentSource="Header" RecognizesAccessKey="True"/>
            <TextBlock x:Name="InputGestureText" Grid.Column="2" Text="{TemplateBinding InputGestureText}" Margin="5,2,0,2" DockPanel.Dock="Right" />
        </Grid>
    </Border>
    <ControlTemplate.Triggers>
        <Trigger Property="Icon" Value="{x:Null}">
            <Setter TargetName="Icon" Property="Visibility" Value="Hidden"/>
        </Trigger>
        <Trigger Property="IsChecked" Value="true">
            <Setter TargetName="CheckMark" Property="Visibility" Value="Visible"/>
        </Trigger>
        <Trigger Property="IsCheckable" Value="true">
            <Setter TargetName="Check" Property="Visibility" Value="Visible"/>
            <Setter TargetName="Icon" Property="Visibility" Value="Hidden"/>
        </Trigger>
        <Trigger Property="IsHighlighted" Value="true">
            <Setter TargetName="Border" Property="Background" Value="{StaticResource ItemHighlight}"/>
        </Trigger>
        <Trigger Property="IsPressed" Value="true">
            <Setter TargetName="Border" Property="Background" Value="{StaticResource MenuClick}"/>
        </Trigger>
        <Trigger Property="IsEnabled" Value="false">
            <Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/>
        </Trigger>
        <Trigger Property="IsEnabled" Value="True">
            <Setter Property="Foreground" Value="White"/>
        </Trigger>
        <Trigger Property="Tag" Value="Title">
            <Setter TargetName="Icon" Property="Visibility" Value="Collapsed"/>
            <Setter Property="Margin" Value="0 15 0 10"/>
            <Setter TargetName="InputGestureText" Property="Visibility" Value="Collapsed"/>
            <Setter TargetName="HeaderHost" Property="Grid.ColumnSpan" Value="3"/>
            <Setter Property="IsHitTestVisible" Value="False"/>
            <Setter Property="Foreground" Value="{StaticResource EnabledForegroundBrush}"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

<!-- SubmenuHeader -->
<ControlTemplate  x:Key="{x:Static MenuItem.SubmenuHeaderTemplateKey}" TargetType="MenuItem">
    <Border Name="Border" Background="{StaticResource MenuClick}">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" SharedSizeGroup="Icon"/>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="Auto" SharedSizeGroup="Shortcut"/>
                <ColumnDefinition Width="13"/>
            </Grid.ColumnDefinitions>
            <ContentPresenter Name="Icon" Margin="3,3,9,3" Height="18" Width="18" VerticalAlignment="Center" ContentSource="Icon"/>
            <ContentPresenter Name="HeaderHost" Grid.Column="1" VerticalAlignment="Center" ContentSource="Header"  RecognizesAccessKey="True"/>
            <TextBlock x:Name="InputGestureText" Grid.Column="2" Text="{TemplateBinding InputGestureText}"  Margin="5,2,2,2" DockPanel.Dock="Right"/>
            <TextBlock Grid.Column="3" HorizontalAlignment="Center" VerticalAlignment="Center" Text="◂" FontSize="13"/>
            <Popup Name="Popup" Placement="Right" HorizontalOffset="5" IsOpen="{TemplateBinding IsSubmenuOpen}" AllowsTransparency="True" Focusable="False" PopupAnimation="Fade">
                <Border Padding="0 8 8 8">
                    <Border Name="SubmenuBorder" SnapsToDevicePixels="True" Background="{StaticResource MenuClick}"  BorderBrush="{StaticResource MenuClick}" BorderThickness="5" >
                    <Border.Effect>
                        <DropShadowEffect ShadowDepth="0" Color="#AAA" Opacity="1" BlurRadius="10"/>
                    </Border.Effect>
                    <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Cycle" />
                </Border>
                </Border>
            </Popup>
        </Grid>
    </Border>
    <ControlTemplate.Triggers>
        <Trigger Property="Icon" Value="{x:Null}">
            <Setter TargetName="Icon" Property="Visibility" Value="Hidden"/>
        </Trigger>
        <Trigger Property="IsHighlighted" Value="true">
            <Setter TargetName="Border" Property="Background" Value="{StaticResource ItemHighlight}"/>
        </Trigger>
        <Trigger Property="IsEnabled" Value="false">
            <Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/>
        </Trigger>
        <Trigger Property="IsEnabled" Value="True">
            <Setter Property="Foreground" Value="White"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

<!-- MenuItem Style -->
<Style x:Key="{x:Type MenuItem}" TargetType="MenuItem">
    <Setter Property="OverridesDefaultStyle" Value="True"/>
    <Style.Triggers>
        <Trigger Property="Role" Value="TopLevelHeader">
            <Setter Property="Template" Value="{StaticResource {x:Static MenuItem.TopLevelHeaderTemplateKey}}"/>
            <Setter Property="Grid.IsSharedSizeScope" Value="true"/>
            <Setter Property="Padding" Value="5 4 5 2"/>
            <Setter Property="Margin" Value="8 0 8 0"/>
        </Trigger>
        <Trigger Property="Role" Value="TopLevelItem">
            <Setter Property="Template" Value="{StaticResource {x:Static MenuItem.TopLevelItemTemplateKey}}"/>
            <Setter Property="Padding" Value="5 4 5 2"/>
            <Setter Property="Margin" Value="8 0 8 0"/>
        </Trigger>
        <Trigger Property="Role" Value="SubmenuHeader">
            <Setter Property="Template" Value="{StaticResource {x:Static MenuItem.SubmenuHeaderTemplateKey}}"/>
        </Trigger>
        <Trigger Property="Role" Value="SubmenuItem">
            <Setter Property="Template"
          Value="{StaticResource {x:Static MenuItem.SubmenuItemTemplateKey}}"/>
        </Trigger>
    </Style.Triggers>
</Style> 

推荐阅读