Lors de mon développement sur Xbox One, je me suis confronté à la modification du design d’un contrôle lorsque celui-ci a le focus.
Il faut savoir que le comportement du focus n’est pas le même entre la souris et la manette. En effet, avec la souris quand l’utilisateur passe sur le contrôle, l’état PointerOver du contrôle est levé dans le VisualState en XAML, or avec la manette, c’est l’état Focused qui est levé (quand celui-ci le possède).
En effet, on ne trouve pas l’état Focused dans le VisualState de tous les contrôles, comme par exemple le bouton. De ce fait, par défaut on se retrouve avec une bordure noire autour du contrôle quand il a le focus.
On en convient, ce n’est pas vraiment très esthétique, de plus, on peut seulement modifier la couleur et l’épaisseur de cette bordure facilement en XAML, ce qui est parfois limité selon le rendu souhaité.
1 2 3 4 5 |
FocusVisualMargin="0" FocusVisualPrimaryBrush="Blue" FocusVisualPrimaryThickness="1" FocusVisualSecondaryBrush="Transparent" FocusVisualSecondaryThickness="0" |
Du coup, la première solution pour modifier le design, est de s’abonner à l’événement GotFocus du contrôle. Et ainsi de faire en code-behind les modifications visuelles que l’on souhaite. Mais on peut en convenir, cette solution n’est pas vraiment adaptée car on ne va pas pouvoir facilement généraliser ce design et il sera difficilement maintenable.
La solution que je vous propose est de créer un nouveau contrôle bouton et d’overrider la méthode OnGotFocus pour y ajouter un nouveau VisualStateManager .
1 2 3 4 5 6 7 8 |
public class FocusSupportedButton : Button { protected override void OnGotFocus(RoutedEventArgs e) { base.OnGotFocus(e); VisualStateManager.GoToState(this, "Focused", false); } } |
Ensuite vous pouvez éditer le style de votre bouton comme cela :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
<Style x:Key="ButtonFocusStyle" TargetType="control:FocusSupportedButton"> <Setter Property="UseSystemFocusVisuals" Value="Flase"/> <Setter Property="FocusVisualMargin" Value="0"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="control:FocusSupportedButton"> <Grid x:Name="RootGrid" Background="{TemplateBinding Background}"> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="Normal"> <Storyboard> <PointerUpThemeAnimation Storyboard.TargetName="RootGrid"/> </Storyboard> </VisualState> <VisualState x:Name="Focused"> <!-- --> <!-- ICI je fais les modifications --> <!-- --> </VisualState> <VisualState x:Name="PointerOver"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="RootGrid"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBackgroundPointerOver}"/> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ContentPresenter"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBorderBrushPointerOver}"/> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonForegroundPointerOver}"/> </ObjectAnimationUsingKeyFrames> <PointerUpThemeAnimation Storyboard.TargetName="RootGrid"/> </Storyboard> </VisualState> <VisualState x:Name="Pressed"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="RootGrid"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBackgroundPressed}"/> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ContentPresenter"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBorderBrushPressed}"/> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonForegroundPressed}"/> </ObjectAnimationUsingKeyFrames> <PointerDownThemeAnimation Storyboard.TargetName="RootGrid"/> </Storyboard> </VisualState> <VisualState x:Name="Disabled"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="RootGrid"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBackgroundDisabled}"/> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ContentPresenter"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBorderBrushDisabled}"/> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter"> <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonForegroundDisabled}"/> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <ContentPresenter x:Name="ContentPresenter" AutomationProperties.AccessibilityView="Raw" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" ContentTemplate="{TemplateBinding ContentTemplate}" ContentTransitions="{TemplateBinding ContentTransitions}" Content="{TemplateBinding Content}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Padding="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> |
Vous pourrez ainsi facilement modifier le nouveau <VisualState x:Name="Focused"> pour réaliser le design que vous souhaitez sur Xbox One.