VisualStateManager on Flyout not highlighting entire area

半世苍凉 提交于 2019-12-08 14:23:26

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!