简体   繁体   English

在使用用户定义模板的菜单项中插入图标

[英]Insert an icon in menu item that uses an user defined Template

I want to have a dropdown menu with custom background color of the menu item.我想要一个带有菜单项自定义背景颜色的下拉菜单。 I was able to achieve this with the help of this answer .我能够在这个答案的帮助下实现这一目标。 The root menu item in my GUI has only an icon with no Header .我的 GUI 中的根菜单项只有一个没有Header的图标。 The code I used to define the menu item icon is as follows:我用来定义菜单项图标的代码如下:

<Style x:Key="MenuIcon" TargetType="{x:Type MenuItem}">
    <Setter Property="SnapsToDevicePixels" Value="True" />
    <Setter Property="OverridesDefaultStyle" Value="True" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type MenuItem}">
                 <Menu Background="Orange">
                     <MenuItem ToolTip="Menu" BorderBrush="White">
                          <MenuItem.Header>
                               <StackPanel
                                   Width="60"
                                   Height="50"
                                   HorizontalAlignment="Center"
                                   VerticalAlignment="Center"
                                   Background="Orange"
                                   Orientation="Horizontal">
                                   <Viewbox
                                       Margin="9"
                                       HorizontalAlignment="Center"
                                       VerticalAlignment="Center"
                                       Stretch="Fill">
                                       <Grid Margin="-8,0,0,0">
                                          <Path
                                              x:Name="MenuIconFillStyle"
                                              HorizontalAlignment="Center"
                                              VerticalAlignment="Center"
                                              Data="M6 36v-3h36v3Zm0-10.5v-3h36v3ZM615v-3h36v3Z"
                                              Fill="White" />
                                       </Grid>
                                   </Viewbox>
                               </StackPanel>
                           </MenuItem.Header>
                        </MenuItem>
                     </Menu>

                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                             <Setter TargetName="MenuIconFillStyle" Property="Fill" Value="Yellow" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

I added the following in the <ControlTemplate x:Key="MenuItemControlTemplate1" TargetType="{x:Type MenuItem}"> taken from here :我在取自此处<ControlTemplate x:Key="MenuItemControlTemplate1" TargetType="{x:Type MenuItem}">中添加了以下内容:

 <ContentPresenter x:Name="Icon" Content="{TemplateBinding Icon}" ContentSource="Icon" HorizontalAlignment="Center" Height="16" Margin="3" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center" Width="16"/>

and the following in the ControlTemplate.Triggers :以及ControlTemplate.Triggers中的以下内容:

<Trigger Property="Icon" Value="True">
     <Setter Property="Visibility" TargetName="Icon" Value="Visible"/>
</Trigger>

The Template="{DynamicResource MenuItemControlTemplate1}" is as follows: Template="{DynamicResource MenuItemControlTemplate1}"如下:

<ControlTemplate x:Key="MenuItemControlTemplate1" TargetType="{x:Type MenuItem}">
            <Border x:Name="templateRoot" 
                    BorderBrush="#535353" 
                    CornerRadius="3" 
                    BorderThickness="1" 
                    Background="{TemplateBinding Background}" 
                    SnapsToDevicePixels="True">
                <Grid VerticalAlignment="Center">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="Auto"/>
                    </Grid.ColumnDefinitions>

                    <ContentPresenter x:Name="Icon" Content="{TemplateBinding Icon}" ContentSource="Icon" HorizontalAlignment="Center" Width="26" Height="16" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center" />
                    <ContentPresenter ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" Grid.Column="1" ContentStringFormat="{TemplateBinding HeaderStringFormat}" ContentSource="Header" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                    <Popup x:Name="PART_Popup"  AllowsTransparency="True" Focusable="False" IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}" Placement="Bottom" HorizontalOffset="-2">
                        <Border x:Name="SubMenuBorder" BorderBrush="#595959" BorderThickness="1" Background="#3A3A3A" Padding="2">
                            <ScrollViewer x:Name="SubMenuScrollViewer" Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, TypeInTargetAssembly={x:Type FrameworkElement}}}">
                                <Grid RenderOptions.ClearTypeHint="Enabled">
                                    <Canvas HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
                                        <Rectangle x:Name="OpaqueRect" Fill="{Binding Background, ElementName=SubMenuBorder}" Height="{Binding ActualHeight, ElementName=SubMenuBorder}" Width="{Binding ActualWidth, ElementName=SubMenuBorder}"/>
                                    </Canvas>
                                    <ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Cycle" Grid.IsSharedSizeScope="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" KeyboardNavigation.TabNavigation="Cycle"/>
                                </Grid>
                            </ScrollViewer>
                        </Border>
                    </Popup>
                </Grid>
            </Border>
            <ControlTemplate.Triggers>
                <Trigger Property="Icon" Value="True">
                    <Setter Property="Visibility" TargetName="Icon" Value="Visible"/>
                </Trigger>
                <Trigger Property="IsSuspendingPopupAnimation" Value="True">
                    <Setter Property="PopupAnimation" TargetName="PART_Popup" Value="None"/>
                </Trigger>
                <Trigger Property="IsHighlighted" Value="True">
                    <Setter Property="Background" TargetName="templateRoot" Value="{StaticResource DarkBrush}"/>
                    <Setter Property="BorderBrush" TargetName="templateRoot" Value="#2C2C2C"/>
                    <Setter Property="BorderThickness" TargetName="templateRoot" Value="1"></Setter>
                </Trigger>

                <Trigger Property="CanContentScroll" SourceName="SubMenuScrollViewer" Value="False">
                    <Setter Property="Canvas.Top" TargetName="OpaqueRect" Value="{Binding VerticalOffset, ElementName=SubMenuScrollViewer}"/>
                    <Setter Property="Canvas.Left" TargetName="OpaqueRect" Value="{Binding HorizontalOffset, ElementName=SubMenuScrollViewer}"/>
                </Trigger>
                <Trigger Property="IsKeyboardFocusWithin" Value="True">
                    <Setter TargetName="templateRoot" Property="Background" Value="{StaticResource Clicked}" />
                    <Setter Property="Header" Value="Test" />
                    <Setter Property="BorderBrush" Value="#2C2C2C"></Setter>
                    <Setter Property="BorderThickness" Value="1"></Setter>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>

The custom background and the icon for the MenuItem is specified as in the following code snippet: MenuItem的自定义背景和图标在以下代码片段中指定:

<Grid Background="#535353">
    <Menu Width="100" Height="22" Margin="10, 10, 5, 5" HorizontalAlignment="Left" Background="White" VerticalAlignment="Top">
        <MenuItem Style="{StaticResource MenuIcon}" Template="{DynamicResource MenuItemControlTemplate1}">
    </Menu>
</Grid>

The icon defined in Style is not rendering in the MenuItem along with the Template ( Template="{DynamicResource MenuItemControlTemplate1}" ) used for setting the background color. Style中定义的图标不会与用于设置背景颜色的模板 ( Template="{DynamicResource MenuItemControlTemplate1}" ) 一起呈现在MenuItem中。 How can this be achieved?如何实现?

Edit编辑

Based on the suggestion of @mm8, I tried to combine the Styles that are responsible for changing the background color (The Style with x:Key="TopLevelHeaderStyle" which is borrowed from here ) and inserting a menu item icon in the root menu and came up with the following:根据@mm8的建议,我尝试结合负责更改背景颜色的Styles(从这里借用的带有x:Key="TopLevelHeaderStyle"的样式)并在根菜单中插入菜单项图标和想出了以下内容:

 <Style x:Key="TopLevelHeaderStyle" TargetType="{x:Type MenuItem}">
            <Setter Property="Background" Value="#000d18"/>
            <Setter Property="Foreground" Value="#d8d8d8"/>
            <Setter Property="Width" Value="72"/>
            <Setter Property="Height" Value="42"/>
            <Setter Property="FontSize" Value="16"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type MenuItem}">
                        <Border x:Name="MenuItemBorder" Width="72" Height="42" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
                            <Grid VerticalAlignment="Center">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto"/>
                                    <ColumnDefinition Width="Auto"/>
                                </Grid.ColumnDefinitions>
                                <ContentPresenter Content="{TemplateBinding Header}" ContentSource="Header" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                                <Popup AllowsTransparency="True" IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" Placement="Bottom" PlacementTarget="{Binding ElementName=MenuItemBorder}"
                                   HorizontalOffset="1" VerticalOffset="-1">
                                    <Border BorderBrush="#414141" Background="#414141">
                                        <ScrollViewer Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, TypeInTargetAssembly={x:Type FrameworkElement}}}">
                                            <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                                        </ScrollViewer>
                                    </Border>
                                </Popup>
                            </Grid>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsHighlighted" Value="True">
                                <Setter Property="Background" Value="#1271C8"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <!--MenuIcon-->
        <Style x:Key="MenuIcon" TargetType="{x:Type MenuItem}" BasedOn="{StaticResource TopLevelHeaderStyle}">
            <Setter Property="SnapsToDevicePixels" Value="True" />
            <Setter Property="OverridesDefaultStyle" Value="True" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type MenuItem}">
                        <Menu>
                            <MenuItem>
                                <MenuItem.Header>
                                    <StackPanel
                            Width="60"
                            Height="50"
                            HorizontalAlignment="Center"
                            VerticalAlignment="Center"
                            Background="Orange"
                            Orientation="Horizontal">
                                        <Viewbox
                                Margin="9"
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center"
                                Stretch="Fill">
                                            <Grid Margin="-8,0,0,0">
                                                <Path x:Name="MenuIconFillStyle"
                                        HorizontalAlignment="Center"
                                        VerticalAlignment="Center"
                                        Fill="White"              
                                        Data="M6 36v-3h36v3Zm0-10.5v-3h36v3ZM6 15v-3h36v3Z"
                                       />
                                            </Grid>
                                        </Viewbox>
                                    </StackPanel>
                                </MenuItem.Header>
                            </MenuItem>
                        </Menu>

And used it as follows:并按如下方式使用它:

<Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="50" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="auto" />
            <ColumnDefinition Width="auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>


        <Menu Grid.Column="0" FontSize="24" HorizontalAlignment="Left" VerticalAlignment="Top">
            <MenuItem  Header="File" Style="{StaticResource TopLevelHeaderStyle}">
                <MenuItem Header="New"/>
                <MenuItem Header="Open"/>
                <MenuItem Header="Close"/>
            </MenuItem>
        </Menu>

        <Menu Grid.Column="1"  FontSize="24" HorizontalAlignment="Left" VerticalAlignment="Top">
            <MenuItem Margin="-11, 0,0,0" Width="50" Header="File" Style="{StaticResource MenuIcon}">
                <MenuItem Header="New1"/>
                <MenuItem Header="Open1"/>
                <MenuItem Header="Close1"/>
            </MenuItem>
        </Menu>
    </Grid>

Now the drop down menu having an icon in the root menu item is not showing the other menu item contents New1 , Open1 and Close1 What mistake am I making?现在在根菜单项中有一个图标的下拉菜单没有显示其他菜单项内容New1Open1Close1我犯了什么错误?

The MenuItem control has a DependencyProperty of type Object named 'Icon'. MenuItem 控件有一个名为“Icon”的类型为 Object 的 DependencyProperty。 This property is reserved for your exact purpose.此属性仅供您使用。

First you need to bind the Data in the Path within your MenuItem ControlTemplate to the Icon property of the parent MenuItem.首先,您需要将 MenuItem ControlTemplate 中 Path 中的数据绑定到父 MenuItem 的 Icon 属性。 Like this:像这样:

<Path x:Name="MenuIconFillStyle"
   HorizontalAlignment="Center"
   VerticalAlignment="Center"
   Data="{TemplateBinding Icon}"
   Fill="White" />

Now you may specify a PathGeometry in XAML like this.现在您可以像这样在 XAML 中指定一个 PathGeometry。 Its contents will be your SVG data:其内容将是您的 SVG 数据:

<PathGeometry x:Key="MySpecialPath">M2 0C0.89687</PathGeometry>

Finally, apply this path using its Key to any MenuItem as a StaticResource:最后,使用其 Key 将此路径作为 StaticResource 应用于任何 MenuItem:

<Menu Width="100" Height="22" Margin="10, 10, 5, 5" HorizontalAlignment="Left" Background="White" VerticalAlignment="Top">
    <MenuItem Template="{DynamicResource MenuItemControlTemplate1}"
              Icon="{StaticResource MySpecialPath}">
</Menu>

If you want a bit more control out of your icons (multiple colors, different size, margin, etc..) It is a bit more involved.如果你想更多地控制你的图标(多个 colors,不同的大小,边距等),它会涉及更多。 Just remember that the 'Path' property on MenuItem is an Object so you can hypothetically use any 'Presenting' element (Does not need to be Path) in your MenuItem ControlTemplate and TemplateBind it to MenuItem.Path - then pass any type of 'Presented' object to the MenuItem (does not need to be PathGeometry).请记住,MenuItem 上的“Path”属性是 Object,因此您可以假设在 MenuItem ControlTemplate 和 TemplateBind 中使用任何“Presenting”元素(不需要是 Path),将其绑定到 MenuItem.Path - 然后传递任何类型的“Presented” ' object 到 MenuItem(不需要是 PathGeometry)。 You can look into using a您可以考虑使用

<ContentPresenter Content="{TemplateBinding Icon}" />

instead of the Path control in the MenuItem ControlTemplate - and then giving literally any "Icon" control to your MenuItem.Path property in your XAML.而不是 MenuItem ControlTemplate 中的 Path 控件 - 然后将任何“图标”控件赋予 XAML 中的 MenuItem.Path 属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM