2016-12-07 6 views
2

Essayer d'utiliser la nouvelle propriété IsDynamicOverflowEnabled sur la CommandBar et j'ai rencontré un problème de style avec le trop-plein. Question est la suivante, lorsque le style de AppBarButton n'est pas surchargée et tombe à la zone de débordement, le point culminant de la AppBarButton étend sur toute la largeur de la Popup et sa détection vol stationnaire/hit est également toute la largeur de la fenêtre contextuelle. Lorsque son style est ignoré, le surlignage ne couvre que la zone du texte (dans ce cas, home) et sa détection de survol/hit est uniquement sur cette zone, même si le style prioritaire est exactement le même que celui dans le generic.xaml.UWP style Changement de style casse AppBarButton automatique du dépassement dynamique

je remarque lors de l'inspection des propriétés à exécution que celles qui ne sont pas surchargées sont appliquées un autre style de la TargetType - FrameworkElement.

De la recherche à travers le generic.xaml, le seul endroit que je peux voir ce genre de changement à un style est dans le CommandBarOverflowPresenter (voir ci-dessous)

<CommandBarOverflowPresenter.ItemContainerStyle> 
    <Style TargetType="FrameworkElement"> 
    <Setter Property="HorizontalAlignment" Value="Stretch" /> 
    <Setter Property="Width" Value="NaN" /> 
    </Style> 
</CommandBarOverflowPresenter.ItemContainerStyle> 

Pour supprimer tous les autres bruits de l'application Je travaille sur, j'ai créé un nouveau projet avec juste un CommandBar sur la page principale et les boutons et le texte nécessaires pour répliquer mon problème. Ci-dessous la MainPage.xaml:

<Page 
    x:Class="App4.MainPage" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="using:App4" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d"> 

    <Page.Resources> 
    <Style x:Key="Style" TargetType="AppBarButton"> 
     <Setter Property="Background" 
       Value="{ThemeResource AppBarButtonBackground}" /> 
     <Setter Property="Foreground" 
       Value="{ThemeResource AppBarButtonForeground}" /> 
     <Setter Property="BorderBrush" 
       Value="{ThemeResource AppBarButtonBorderBrush}" /> 
     <Setter Property="HorizontalAlignment" 
       Value="Left" /> 
     <Setter Property="VerticalAlignment" 
       Value="Top" /> 
     <Setter Property="FontFamily" 
       Value="{ThemeResource ContentControlThemeFontFamily}" /> 
     <Setter Property="FontWeight" 
       Value="Normal" /> 
     <Setter Property="Width" 
       Value="68" /> 
     <Setter Property="UseSystemFocusVisuals" 
       Value="True" /> 
     <Setter Property="AllowFocusOnInteraction" 
       Value="False" /> 
     <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="AppBarButton"> 
      <Grid x:Name="Root" 
        MinWidth="{TemplateBinding MinWidth}" 
        MaxWidth="{TemplateBinding MaxWidth}" 
        Background="{TemplateBinding Background}" 
        BorderBrush="{TemplateBinding BorderBrush}" 
        BorderThickness="{TemplateBinding BorderThickness}"> 
       <Grid.Resources> 
       <Style x:Name="LabelOnRightStyle" 
         TargetType="AppBarButton"> 
        <Setter Property="Width" 
          Value="NaN" /> 
       </Style> 
       </Grid.Resources> 
       <VisualStateManager.VisualStateGroups> 
       <VisualStateGroup x:Name="ApplicationViewStates"> 
        <VisualState x:Name="FullSize" /> 
        <VisualState x:Name="Compact"> 
        <Storyboard> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" 
                Storyboard.TargetProperty="Visibility"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="Collapsed" /> 
         </ObjectAnimationUsingKeyFrames> 
        </Storyboard> 
        </VisualState> 
        <VisualState x:Name="LabelOnRight"> 
        <Storyboard> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" 
                Storyboard.TargetProperty="Margin"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="12,14,0,14" /> 
         </ObjectAnimationUsingKeyFrames> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" 
                Storyboard.TargetProperty="MinHeight"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="{ThemeResource AppBarThemeCompactHeight}" /> 
         </ObjectAnimationUsingKeyFrames> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" 
                Storyboard.TargetProperty="(Grid.Row)"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="0" /> 
         </ObjectAnimationUsingKeyFrames> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" 
                Storyboard.TargetProperty="(Grid.Column)"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="1" /> 
         </ObjectAnimationUsingKeyFrames> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" 
                Storyboard.TargetProperty="TextAlignment"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="Left" /> 
         </ObjectAnimationUsingKeyFrames> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" 
                Storyboard.TargetProperty="Margin"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="8,15,12,17" /> 
         </ObjectAnimationUsingKeyFrames> 
        </Storyboard> 
        </VisualState> 
        <VisualState x:Name="LabelCollapsed"> 
        <Storyboard> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" 
                Storyboard.TargetProperty="MinHeight"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="{ThemeResource AppBarThemeCompactHeight}" /> 
         </ObjectAnimationUsingKeyFrames> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" 
                Storyboard.TargetProperty="Visibility"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="Collapsed" /> 
         </ObjectAnimationUsingKeyFrames> 
        </Storyboard> 
        </VisualState> 
        <VisualState x:Name="Overflow"> 
        <Storyboard> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" 
                Storyboard.TargetProperty="Visibility"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="Collapsed" /> 
         </ObjectAnimationUsingKeyFrames> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="OverflowTextLabel" 
                Storyboard.TargetProperty="Visibility"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="Visible" /> 
         </ObjectAnimationUsingKeyFrames> 
        </Storyboard> 
        </VisualState> 
        <VisualState x:Name="OverflowWithToggleButtons"> 
        <Storyboard> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" 
                Storyboard.TargetProperty="Visibility"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="Collapsed" /> 
         </ObjectAnimationUsingKeyFrames> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="OverflowTextLabel" 
                Storyboard.TargetProperty="Visibility"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="Visible" /> 
         </ObjectAnimationUsingKeyFrames> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="OverflowTextLabel" 
                Storyboard.TargetProperty="Margin"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="38,0,12,0" /> 
         </ObjectAnimationUsingKeyFrames> 
        </Storyboard> 
        </VisualState> 
       </VisualStateGroup> 
       <VisualStateGroup x:Name="CommonStates"> 
        <VisualState x:Name="Normal"> 
        <Storyboard> 
         <PointerUpThemeAnimation Storyboard.TargetName="OverflowTextLabel" /> 
        </Storyboard> 
        </VisualState> 
        <VisualState x:Name="PointerOver"> 
        <Storyboard> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Root" 
                Storyboard.TargetProperty="Background"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="{ThemeResource AppBarButtonBackgroundPointerOver}" /> 
         </ObjectAnimationUsingKeyFrames> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Root" 
                Storyboard.TargetProperty="BorderBrush"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="{ThemeResource AppBarButtonBorderBrushPointerOver}" /> 
         </ObjectAnimationUsingKeyFrames> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" 
                Storyboard.TargetProperty="Foreground"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="{ThemeResource AppBarButtonForegroundPointerOver}" /> 
         </ObjectAnimationUsingKeyFrames> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" 
                Storyboard.TargetProperty="Foreground"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="{ThemeResource AppBarButtonForegroundPointerOver}" /> 
         </ObjectAnimationUsingKeyFrames> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="OverflowTextLabel" 
                Storyboard.TargetProperty="Foreground"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="{ThemeResource AppBarButtonForegroundPointerOver}" /> 
         </ObjectAnimationUsingKeyFrames> 
         <PointerUpThemeAnimation Storyboard.TargetName="OverflowTextLabel" /> 
        </Storyboard> 
        </VisualState> 
        <VisualState x:Name="Pressed"> 
        <Storyboard> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Root" 
                Storyboard.TargetProperty="Background"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="{ThemeResource AppBarButtonBackgroundPressed}" /> 
         </ObjectAnimationUsingKeyFrames> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Root" 
                Storyboard.TargetProperty="BorderBrush"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="{ThemeResource AppBarButtonBorderBrushPressed}" /> 
         </ObjectAnimationUsingKeyFrames> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" 
                Storyboard.TargetProperty="Foreground"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="{ThemeResource AppBarButtonForegroundPressed}" /> 
         </ObjectAnimationUsingKeyFrames> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" 
                Storyboard.TargetProperty="Foreground"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="{ThemeResource AppBarButtonForegroundPressed}" /> 
         </ObjectAnimationUsingKeyFrames> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="OverflowTextLabel" 
                Storyboard.TargetProperty="Foreground"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="{ThemeResource AppBarButtonForegroundPressed}" /> 
         </ObjectAnimationUsingKeyFrames> 
         <PointerDownThemeAnimation Storyboard.TargetName="OverflowTextLabel" /> 
        </Storyboard> 
        </VisualState> 
        <VisualState x:Name="Disabled"> 
        <Storyboard> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Root" 
                Storyboard.TargetProperty="Background"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="{ThemeResource AppBarButtonBackgroundDisabled}" /> 
         </ObjectAnimationUsingKeyFrames> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Root" 
                Storyboard.TargetProperty="BorderBrush"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="{ThemeResource AppBarButtonBorderBrushDisabled}" /> 
         </ObjectAnimationUsingKeyFrames> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" 
                Storyboard.TargetProperty="Foreground"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="{ThemeResource AppBarButtonForegroundDisabled}" /> 
         </ObjectAnimationUsingKeyFrames> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" 
                Storyboard.TargetProperty="Foreground"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="{ThemeResource AppBarButtonForegroundDisabled}" /> 
         </ObjectAnimationUsingKeyFrames> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetName="OverflowTextLabel" 
                Storyboard.TargetProperty="Foreground"> 
         <DiscreteObjectKeyFrame KeyTime="0" 
               Value="{ThemeResource AppBarButtonForegroundDisabled}" /> 
         </ObjectAnimationUsingKeyFrames> 
        </Storyboard> 
        </VisualState> 
       </VisualStateGroup> 
       <VisualStateGroup x:Name="InputModeStates"> 
        <VisualState x:Name="InputModeDefault" /> 
        <VisualState x:Name="TouchInputMode"> 
        <VisualState.Setters> 
         <Setter Target="OverflowTextLabel.Padding" 
           Value="0,11,0,13" /> 
        </VisualState.Setters> 
        </VisualState> 
        <VisualState x:Name="GameControllerInputMode"> 
        <VisualState.Setters> 
         <Setter Target="OverflowTextLabel.Padding" 
           Value="0,11,0,13" /> 
        </VisualState.Setters> 
        </VisualState> 
       </VisualStateGroup> 
       </VisualStateManager.VisualStateGroups> 
       <Grid x:Name="ContentRoot" 
        MinHeight="{ThemeResource AppBarThemeMinHeight}"> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition Width="*" /> 
        <ColumnDefinition Width="Auto" /> 
       </Grid.ColumnDefinitions> 
       <Grid.RowDefinitions> 
        <RowDefinition Height="Auto" /> 
        <RowDefinition Height="Auto" /> 
       </Grid.RowDefinitions> 
       <ContentPresenter x:Name="Content" 
            Height="20" 
            Margin="0,14,0,4" 
            Content="{TemplateBinding Icon}" 
            Foreground="{TemplateBinding Foreground}" 
            HorizontalAlignment="Stretch" 
            AutomationProperties.AccessibilityView="Raw" /> 
       <TextBlock x:Name="TextLabel" 
          Grid.Row="1" 
          Text="{TemplateBinding Label}" 
          Foreground="{TemplateBinding Foreground}" 
          FontSize="12" 
          FontFamily="{TemplateBinding FontFamily}" 
          TextAlignment="Center" 
          TextWrapping="Wrap" 
          Margin="2,0,2,6" /> 
       </Grid> 
       <TextBlock x:Name="OverflowTextLabel" 
         Text="{TemplateBinding Label}" 
         Foreground="{TemplateBinding Foreground}" 
         FontSize="15" 
         FontFamily="{TemplateBinding FontFamily}" 
         TextAlignment="Left" 
         TextTrimming="Clip" 
         TextWrapping="NoWrap" 
         HorizontalAlignment="Stretch" 
         VerticalAlignment="Center" 
         Margin="12,0,12,0" 
         Padding="0,5,0,7" 
         Visibility="Collapsed" /> 
      </Grid> 
      </ControlTemplate> 
     </Setter.Value> 
     </Setter> 
    </Style> 
    </Page.Resources> 

    <Page.TopAppBar> 
    <CommandBar IsDynamicOverflowEnabled="True"> 
     <CommandBar.Content> 
     <TextBlock Text="Text to force the buttons to drop off at some point when the screen is resized" /> 
     </CommandBar.Content> 
     <CommandBar.PrimaryCommands> 
     <AppBarButton Label="Edit" 
         Icon="Edit" /> 
     <AppBarButton Label="People" 
         Icon="People" /> 
     <AppBarButton Label="Really long text should should make overflow wider" 
         Icon="Highlight" /> 
     <AppBarButton Label="Home" 
         Icon="Home" 
         Style="{StaticResource Style}" /> 
     </CommandBar.PrimaryCommands> 
    </CommandBar> 
    </Page.TopAppBar> 
</Page> 

Comme vous pouvez le voir, j'ai 1 CommandBar, 1 TextBlock dans le contenu du CommandBar et 4 AppBarButtons dans les PrimaryCommands du CommandBar. Seulement 1 des AppBarButtons Styles est surchargée (la maison un) et le style dont il est outrepassée avec est saisi directement à partir du generic.xaml de cet endroit - C: \ Program Files (x86) \ Windows Kits \ 10 \ DesignTime \ CommonConfiguration \ Neutre \ UAP \ 10.0.14393.0 \ Générique

Pourquoi cela? Et y a-t-il des solutions de contournement connues?

Répondre

2

Comme vous le savez, alors qu'un AppBarButton est ajouté dans SecondaryCommands, il s'affichera dans Popup. Et si vous vérifiez avec Live Visual Tree dans Visual Studio, vous trouverez le AppBarButton est ajouté dans un CommandBarOverflowPresenter nommé « SecondaryItemsControl ».
enter image description here

Le style que vous avez trouvé sous CommandBarOverflowPresenter.ItemContainerStyle est utilisé pour réinitialiser AppBarButton « Width et HorizontalAlignment propriété s que par défaut AppBarButton » s Width est 68 et HorizontalAlignment est réglé sur Left et si nous utilisons le style par défaut, la AppBarButton ne peut pas prendre toute la largeur du Popup.

<Setter Property="HorizontalAlignment" Value="Left" /> 
<Setter Property="Width" Value="68"/> 

Cependant, le style sous CommandBarOverflowPresenter.ItemContainerStyle applique uniquement sur la AppBarButton avec des styles implicites. Si vous définissez explicitement la propriété Style de AppBarButton, il perdra sa fonction. Et c'est la raison pour laquelle le changement de style de AppBarButton casse le style automatique du débordement dynamique.

Pour contourner ce problème, vous pouvez essayer de changer la Width et HorizontalAlignment biens comme ce sous CommandBarOverflowPresenter.ItemContainerStyle et définir MiniWidth pour limiter la largeur de AppBarButton.

<Style x:Key="Style" TargetType="AppBarButton"> 
    <Setter Property="HorizontalAlignment" Value="Stretch" /> 
    <Setter Property="Width" Value="Auto" /> 
    <Setter Property="MinWidth" Value="68" /> 
    ... 
</Style> 

PS: Cette solution de contournement peut être pas adapté à tous les scénarios, en particulier lorsque le AppBarButton a une longue Label. Vous devrez peut-être déterminer s'il convient de l'utiliser en fonction de votre scénario.

Mise à jour:

Votre réponse soulève une autre question, pourquoi seuls peuvent styles implicites hériter de ce CommandBarOverflowPresenter.ItemContainerStyle?

Ceci est en rapport avec Lookup behavior for XAML resource references. Vous pouvez penser que Style ont été définis comme ayant la plus haute priorité. Une fois que vous avez défini la propriété Style, le système XAML ne recherchera pas d'autres styles.

Ref ResourceDictionary and XAML resource references:

Le cadre XAML examine également des ressources de style implicites (ceux qui utilisent TargetType plutôt que x:Key ou x:Name) lorsqu'il décide quel style & modèle à utiliser pour un contrôle qui n » t définir les propriétés Style et ContentTemplate ou ItemTemplate.

donc une fois que vous définissez Style pour AppBarButton, le style implicite sous CommandBarOverflowPresenter.ItemContainerStyle ne fonctionnera pas.

Voici un exemple simple qui illustre ce comportement.

<Page ...> 
    <Page.Resources> 
     <Style x:Key="ListViewItemStyle1" TargetType="ListViewItem"> 
      <Setter Property="Background" Value="Red" /> 
     </Style> 
    </Page.Resources> 

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
     <ListView> 
      <ListView.ItemContainerStyle> 
       <Style TargetType="ListViewItem"> 
        <Setter Property="Background" Value="Green" /> 
        <Setter Property="Foreground" Value="White" /> 
       </Style> 
      </ListView.ItemContainerStyle> 
      <ListViewItem Style="{StaticResource ListViewItemStyle1}">1</ListViewItem> 
      <ListViewItem Background="Blue">2</ListViewItem> 
      <ListViewItem>3</ListViewItem> 
      <ListViewItem>4</ListViewItem> 
     </ListView> 
    </Grid> 
</Page> 

Et il ressemble:
enter image description here

Comme vous pouvez le voir, pour le premier élément, comme je l'ai défini la propriété Style explicitement, il ne sera pas utiliser le style sous ListView.ItemContainerStyle. Pour le deuxième élément, comme je n'ai pas défini la propriété Style, il utilisera le style implicite sous ListView.ItemContainerStyle, mais la propriété qui a été définie explicitement a une priorité plus élevée. Le premier plan de cet élément est blanc mais son arrière-plan est bleu. Et pour les troisième et quatrième éléments, comme ils utilisent le style par défaut qui a la priorité la plus basse, le style implicite sous ListView.ItemContainerStyle sera utilisé à la place du style par défaut.

+0

Merci pour l'info et la solution de contournement potentielle, je ne pense pas que cela fonctionnera pour mon scénario car j'ai de longues étiquettes (ish). Votre réponse soulève une autre question, pourquoi seuls les styles implicites peuvent-ils hériter de ce 'CommandBarOverflowPresenter.ItemContainerStyle'? Cela me semble plutôt un bug que ce 'Style' ne serait plus hérité parce que ** I ** avait surchargé un' Style' qui ne lui était pas lié. – jsmyth886

+0

@ jsmyth886 Ce n'est pas un bug. C'est prévu et intentionnel. Le problème ici est lié au comportement de recherche pour les références de ressources XAML. Veuillez vérifier ma réponse mise à jour. Et je crains qu'il n'y ait pas de solution "taille unique". Vous devez équilibrer entre la fonction de débordement dynamique et le style personnalisé et essayer de trouver la meilleure solution pour votre scénario. –

+0

@ jsmyth886 Je ne sais pas quel est votre scénario actuel. Mais comme je l'ai expliqué, ce problème se produit lorsque nous définissons explicitement la propriété 'Style'.Vous pouvez essayer de définir votre style personnalisé comme un style implicite qui s'applique à toutes les propriétés s et set pour différents 'AppBarButton'. –