问题
I have a VisualStateManager that controls the background color when the pointer is over the item. The problem is, it doesn't highlight the entire area, just a small portion around the text and icon. Here's my code:
Not fully highlighted
<FlyoutBase.AttachedFlyout>
<MenuFlyout>
<MenuFlyoutItem Text="Delete" Click="DeleteMenuItemClick">
<MenuFlyoutItem.Template>
<ControlTemplate TargetType="MenuFlyoutItem">
<Grid>
<StackPanel Orientation="Horizontal" Padding="0">
<SymbolIcon Symbol="Delete" Margin="10,0" />
<TextBlock Text="{TemplateBinding Text}" />
</StackPanel>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition To="PointerOver"
GeneratedDuration="0:0:0.5"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="Flyout"
Storyboard.TargetProperty="Color"
To="{StaticResource SystemAltHighColor}" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.Background>
<SolidColorBrush x:Name="Flyout"
Color="{TemplateBinding Background}">
</SolidColorBrush>
</Grid.Background>
</Grid>
</ControlTemplate>
</MenuFlyoutItem.Template>
</MenuFlyoutItem>
</MenuFlyout>
</FlyoutBase.AttachedFlyout>
EDIT:
Thanks everyone for the answers. I'll look into those solutions when I can; I did end up doing something a little different - making the area a bit bigger so you can see the highlight by adding padding. It's not quite what I wanted, which is why I'll look into these.
回答1:
It doesn't highlight the entire area because you are using Visual State in MenuFlyoutItem
and the highlight area is the area of your MenuFlyoutItem
.
You can see this in Visual Studio's Live Visual Tree. To see this clearly, we can run the app in Simulator and check "Display layout adorners in the running application" in Live Visual Tree. Then you will see the size of the MenuFlyoutItem
.
When selecting MenuFlyoutItem
in Live Visual Tree, its area will be blue. It's not clear in my picture, you can try it yourself.
So to highlight the entire area, we need let the MenuFlyoutItem
fill the full MenuFlyoutPresenter
and to do this, we need edit the style of MenuFlyout
by setting MenuFlyoutPresenterStyle
. You can find the default MenuFlyoutPresenter
style at MenuFlyoutPresenter styles and templates.
To set MenuFlyoutPresenterStyle
, we can copy the default style from website or in Visual Studio, select the "[MenuFlyout]" in "Document Outline" and right click, then select "Edit Additional Templates" → "Edit MenuFlyoutPresenterStyle" → "Edit a Copy...".
In the style, we need remove the Margin
in ItemsPresenter
by setting it to 0
<ItemsPresenter Margin="0"/>
Then there will be no margin around the MenuFlyoutItem
. However this is not enough because MenuFlyoutPresenter
has a 32 min height:
<x:Double x:Key="MenuFlyoutThemeMinHeight">32</x:Double>
If the height of MenuFlyoutItem
is less than 32, it also can't highlight the entire area. To solve this, you can set MinHeight
property to 0
.
<Setter Property="MinHeight" Value="0"/>
Or increase the height of MenuFlyoutItem
like setting Margin
in your StackPanel
:
<StackPanel Orientation="Horizontal" Margin="0,8">
<SymbolIcon Margin="10,0" Symbol="Delete" />
<TextBlock Text="{TemplateBinding Text}" />
</StackPanel>
The complete MenuFlyoutPresenterStyle may like following:
<Style x:Key="MyMenuFlyoutPresenterStyle" TargetType="MenuFlyoutPresenter">
<Setter Property="Background" Value="{ThemeResource SystemControlBackgroundChromeMediumLowBrush}" />
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundChromeHighBrush}" />
<Setter Property="BorderThickness" Value="{ThemeResource FlyoutBorderThemeThickness}" />
<Setter Property="Padding" Value="{ThemeResource MenuFlyoutPresenterThemePadding}" />
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Disabled" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Auto" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
<Setter Property="ScrollViewer.IsHorizontalRailEnabled" Value="False" />
<Setter Property="ScrollViewer.IsVerticalRailEnabled" Value="False" />
<Setter Property="ScrollViewer.ZoomMode" Value="Disabled" />
<Setter Property="MaxWidth" Value="{ThemeResource FlyoutThemeMaxWidth}" />
<Setter Property="MinHeight" Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="MenuFlyoutPresenter">
<Grid Background="{TemplateBinding Background}">
<ScrollViewer x:Name="MenuFlyoutPresenterScrollViewer" AutomationProperties.AccessibilityView="Raw" HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}" HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}" IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}" IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}" Margin="{TemplateBinding BorderThickness}" MinWidth="{Binding TemplateSettings.FlyoutContentMinWidth, RelativeSource={RelativeSource Mode=TemplatedParent}}" Padding="{TemplateBinding Padding}" VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}" VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}" ZoomMode="{TemplateBinding ScrollViewer.ZoomMode}">
<ItemsPresenter Margin="0" />
</ScrollViewer>
<Border x:Name="MenuFlyoutPresenterBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
回答2:
edit the style of MenuFlyout and you will achieve what you want, I will do it something like that
<FlyoutBase.AttachedFlyout>
<MenuFlyout>
<MenuFlyout.MenuFlyoutPresenterStyle>
<Style TargetType="MenuFlyoutPresenter">
<Setter Property="Background" Value="Transparent"/>
</Style>
</MenuFlyout.MenuFlyoutPresenterStyle>
<MenuFlyoutItem Text="Delete" Click="DeleteMenuItemClick">
<MenuFlyoutItem.Template>
<ControlTemplate TargetType="MenuFlyoutItem">
<Grid>
<StackPanel Orientation="Horizontal" Padding="0">
<SymbolIcon Symbol="Delete" Margin="10,0" />
<TextBlock Text="{TemplateBinding Text}" />
</StackPanel>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition To="PointerOver" GeneratedDuration="0:0:0.5"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="Flyout" Storyboard.TargetProperty="Color" To="{StaticResource SystemAltHighColor}" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.Background>
<SolidColorBrush x:Name="Flyout" Color="{TemplateBinding Background}"></SolidColorBrush>
</Grid.Background>
</Grid>
</ControlTemplate>
</MenuFlyoutItem.Template>
</MenuFlyoutItem>
</MenuFlyout>
</FlyoutBase.AttachedFlyout>
来源:https://stackoverflow.com/questions/35763131/visualstatemanager-on-flyout-not-highlighting-entire-area