C # WPF - Пользовательский элемент меню Фон при наведении - PullRequest
0 голосов
/ 20 ноября 2018

Как изменить фон пользовательского элемента меню при наведении на него курсора?Я изменил свойство фона, но оно не меняется, оно остается синим цветом по умолчанию.Я также попытался изменить стиль триггера при наведении, но опять-таки, это не помогает, его игнорируют.

Идея состоит в том, чтобы навести курсор на элемент меню, и вместо синего цвета по умолчанию должен появиться пользовательский цвет.color.

Вот код:

    <Style TargetType="{x:Type Menu}" x:Key="TopbarMenu" BasedOn="{StaticResource BaseStyle}">
    <Setter Property="WindowChrome.IsHitTestVisibleInChrome" Value="True"/>
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="Foreground" Value="{StaticResource WhiteBrush}"/>
    <Setter Property="BorderThickness" Value="0"/>
    <Setter Property="HorizontalAlignment" Value="Center"/>
    <Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<Style TargetType="{x:Type MenuItem}" x:Key="DropdownMenuButton" BasedOn="{StaticResource BaseStyle}">
    <Setter Property="TextOptions.TextFormattingMode" Value="Display"/>
    <Setter Property="BorderThickness" Value="0"/>
    <Setter Property="Margin" Value="6 0 6 0"/>
</Style>

Я думаю, что это что-то связано с шаблонами, но я не очень разбираюсь в шаблонах, и я могу быть в корне ошибочным и проблемаможет быть что-то еще.

1 Ответ

0 голосов
/ 20 ноября 2018

Это то, как я это делаю ... прекрасно работает для меня:

<ControlTemplate TargetType="{x:Type MenuItem}" x:Key="MenuItemTemplate">
    <Border x:Name="Border" Padding="10,5,10,5" BorderThickness="0" Margin="0">
        <ContentPresenter ContentSource="Header" x:Name="HeaderHost" RecognizesAccessKey="True" />
    </Border>
    <ControlTemplate.Triggers>
        <Trigger Property="IsHighlighted" Value="true">
            <Setter Property="Background" TargetName="Border" Value="Blue"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

и используется с:

<MenuItem Template="{StaticResource MenuItemTemplate}" Header="test" />

[EDIT]

В соответствии с запросом есть некоторые вещи для правильной поддержки подменю:

<ControlTemplate TargetType="MenuItem" x:Key="rootMenuItem">
    <Border x:Name="templateRoot" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" 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" Height="16" Margin="3" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center" Width="16"/>
            <Path x:Name="GlyphPanel" Data="F1M10,1.2L4.7,9.1 4.5,9.1 0,5.2 1.3,3.5 4.3,6.1 8.3,0 10,1.2z" Fill="{TemplateBinding Foreground}" FlowDirection="LeftToRight" Margin="3" Visibility="Collapsed" 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">
                <Border x:Name="SubMenuBorder" BorderBrush="#FF999999" BorderThickness="1" Background="#FFF0F0F0" 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>
                            <Rectangle Fill="#FFD7D7D7" HorizontalAlignment="Left" Margin="29,2,0,2" Width="1"/>
                            <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="IsSuspendingPopupAnimation" Value="True">
            <Setter Property="PopupAnimation" TargetName="PART_Popup" Value="None"/>
        </Trigger>
        <Trigger Property="Icon" Value="{x:Null}">
            <Setter Property="Visibility" TargetName="Icon" Value="Collapsed"/>
        </Trigger>
        <Trigger Property="IsChecked" Value="True">
            <Setter Property="Visibility" TargetName="GlyphPanel" Value="Visible"/>
            <Setter Property="Visibility" TargetName="Icon" Value="Collapsed"/>
        </Trigger>
        <Trigger Property="IsHighlighted" Value="True">
            <Setter Property="Background" TargetName="templateRoot" Value="BLUE"/>
            <Setter Property="BorderBrush" TargetName="templateRoot" Value="#FF26A0DA"/>
        </Trigger>
        <Trigger Property="IsEnabled" Value="False">
            <Setter Property="TextElement.Foreground" TargetName="templateRoot" Value="#FF707070"/>
            <Setter Property="Fill" TargetName="GlyphPanel" Value="#FF707070"/>
        </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>
    </ControlTemplate.Triggers>
</ControlTemplate>



<Style TargetType="MenuItem">
    <Setter Property="Template">
        <Setter.Value>

            <ControlTemplate TargetType="{x:Type MenuItem}">
                <Border x:Name="templateRoot" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
                    <Grid Margin="-1">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition MinWidth="22" SharedSizeGroup="MenuItemIconColumnGroup" Width="Auto"/>
                            <ColumnDefinition Width="13"/>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="30"/>
                            <ColumnDefinition SharedSizeGroup="MenuItemIGTColumnGroup" Width="Auto"/>
                            <ColumnDefinition Width="20"/>
                        </Grid.ColumnDefinitions>
                        <ContentPresenter x:Name="Icon" Content="{TemplateBinding Icon}" ContentSource="Icon" HorizontalAlignment="Center" Height="16" Margin="3" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center" Width="16"/>
                        <Border x:Name="GlyphPanel" BorderBrush="#FF26A0DA" BorderThickness="1" Background="#3D26A0DA" Height="22" Margin="-1,0,0,0" Visibility="Hidden" VerticalAlignment="Center" Width="22">
                            <Path x:Name="Glyph" Data="F1M10,1.2L4.7,9.1 4.5,9.1 0,5.2 1.3,3.5 4.3,6.1 8.3,0 10,1.2z" Fill="#FF212121" FlowDirection="LeftToRight" Height="11" Width="9"/>
                        </Border>
                        <ContentPresenter ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" Grid.Column="2" ContentStringFormat="{TemplateBinding HeaderStringFormat}" ContentSource="Header" HorizontalAlignment="Left" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center"/>
                        <TextBlock Grid.Column="4" Margin="{TemplateBinding Padding}" Opacity="0.7" Text="{TemplateBinding InputGestureText}" VerticalAlignment="Center"/>
                        <Path x:Name="RightArrow" Grid.Column="5" Data="M0,0L4,3.5 0,7z" Fill="#FF212121" HorizontalAlignment="Left" Margin="10,0,0,0" VerticalAlignment="Center"/>
                        <Popup x:Name="PART_Popup" AllowsTransparency="True" Focusable="False" HorizontalOffset="-2" IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}" Placement="Right" VerticalOffset="-3">
                            <Border x:Name="SubMenuBorder" BorderBrush="#FF999999" BorderThickness="1" Background="#FFF0F0F0" 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>
                                        <Rectangle Fill="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}" HorizontalAlignment="Left" Margin="29,2,0,2" Width="1"/>
                                        <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="IsSuspendingPopupAnimation" Value="True">
                        <Setter Property="PopupAnimation" TargetName="PART_Popup" Value="None"/>
                    </Trigger>
                    <Trigger Property="Icon" Value="{x:Null}">
                        <Setter Property="Visibility" TargetName="Icon" Value="Collapsed"/>
                    </Trigger>
                    <Trigger Property="IsChecked" Value="True">
                        <Setter Property="Visibility" TargetName="GlyphPanel" Value="Visible"/>
                        <Setter Property="Visibility" TargetName="Icon" Value="Collapsed"/>
                    </Trigger>
                    <Trigger Property="IsHighlighted" Value="True">
                        <Setter Property="Background" TargetName="templateRoot" Value="BLUE"/>
                        <Setter Property="BorderBrush" TargetName="templateRoot" Value="#FF26A0DA"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter Property="TextElement.Foreground" TargetName="templateRoot" Value="#FF707070"/>
                        <Setter Property="Fill" TargetName="Glyph" Value="#FF707070"/>
                        <Setter Property="Fill" TargetName="RightArrow" Value="#FF707070"/>
                    </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>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

и тест использования:

<Menu HorizontalAlignment="Center" VerticalAlignment="Center">
    <MenuItem Header="test" Template="{StaticResource rootMenuItem}">
        <MenuItem Header="test" >
            <MenuItem Header="test">
                <MenuItem Header="test">
                    <MenuItem Header="test">
                        <MenuItem Header="test">
                            <MenuItem Header="test" />
                            <MenuItem Header="test" />
                        </MenuItem>
                        <MenuItem Header="test" />
                    </MenuItem>
                    <MenuItem Header="test" />
                </MenuItem>
                <MenuItem Header="test" />
            </MenuItem>
            <MenuItem Header="test">
                <MenuItem Header="test">
                    <MenuItem Header="test" />
                    <MenuItem Header="test" />
                </MenuItem>
                <MenuItem Header="test">
                    <MenuItem Header="test">
                        <MenuItem Header="test" />
                        <MenuItem Header="test" />
                    </MenuItem>
                    <MenuItem Header="test" />
                </MenuItem>
            </MenuItem>
        </MenuItem>
    </MenuItem>
    <MenuItem Header="test" Template="{StaticResource rootMenuItem}">
        <MenuItem Header="test">
            <MenuItem Header="test" />
            <MenuItem Header="test" />
        </MenuItem>
    </MenuItem>
</Menu>

Осторожно, у корневого элемента есть другойшаблон, чем дочерние элементы!в этой демонстрации это делается с помощью статической привязки шаблона к корневым элементам, но в реальном случае вы можете сделать это с помощью селектора стиля, подобного следующему:

<Style TargetType="{x:Type MenuItem}" x:Key="{x:Type MenuItem}">
    <Setter Property="OverridesDefaultStyle" Value="True"/>
    <Style.Triggers>
        <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>

[/ EDIT]

[EDIT2] Чтобы стрелка исчезла, вам нужен StyleSelector, как уже упоминалось.этот класс должен быть реализован при условии, что у вас есть два стиля с именами «MenuItemWithChildren» и «MenuItemWithoutChildren»

class ItemStyleSelector : StyleSelector
{
    public override Style SelectStyle(object item, DependencyObject container)
    {
        if(item is MenuItem mItem)
        {
            if(mItem.Items.Count > 0)
            {
                return App.Current.Resources["MenuItemWithChildren"] as Style;
            }
            else
            {
                return App.Current.Resources["MenuItemWithoutChildren"] as Style;
            }
        }

        return base.SelectStyle(item, container);
    }
}

, тогда вы должны определить два разных стиля и шаблоны для каждого из элементов с потомками и без них: Важно: они должны быть определены в app.xaml или некотором ресурсном словаре, который связан там, иначе класс ItemStyleSelector не найдет их.Например, Window.Resources не будут найдены.

<Style TargetType="MenuItem" x:Key="MenuItemWithChildren">
    <Setter Property="ItemContainerStyleSelector" Value="{StaticResource ItemStyleSelector}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type MenuItem}">
                [Your Template goes here]
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<Style TargetType="MenuItem" x:Key="MenuItemWithoutChildren">
    <Setter Property="ItemContainerStyleSelector" Value="{StaticResource ItemStyleSelector}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type MenuItem}">
                [Your Template goes here]
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

также сам ваш Styleselctor и стиль по умолчанию для пункта меню

<local:ItemStyleSelector x:Key="ItemStyleSelector" />
<Style TargetType="MenuItem">
    <Setter Property="ItemContainerStyleSelector" Value="{StaticResource ItemStyleSelector}" />
</Style>

и объявите выбор в меню:

<Menu ItemContainerStyleSelector="{StaticResource ItemStyleSelector}">
    <MenuItem Header="test" Template="{StaticResource rootMenuItem}">
        <MenuItem Header="test">
            <MenuItem Header="test" />
            <MenuItem Header="test" />
        </MenuItem>
    </MenuItem>
</Menu>

[/ EDIT2]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...