Positionner correctement le contrôle Slider

Peut.être n’avez vous jamais utilisé un contrôle Slider dans vos applications ?
C’est un control qui permet de faire varier une valeur en faisant glisser un bouton.
Voici à quoi il ressemble (empilé entre deux TextBlocks Hello) :

<TextBlock Text="Hello"></TextBlock>
<Slider/>
<TextBlock Text="Hello"></TextBlock>

;

Drole de marge

Ce control fonctionne très bien mais comme on le voit dans la capture d’écran effectuée sur Blend la marge qui le sépare des autres contrôles est anormalement grande verticalement (surtout vers le bas).
Qu’a cela ne tienne on va lui mettre une marge qui nous convienne d’avantage :

<TextBlock Text="Hello"></TextBlock>
<Slider Margin="0"/>
<TextBlock Text="Hello"></TextBlock>

Cela semble ne rien changer car la marge est bien prise en compte mais à partir du pourtour existant.
ici une capture avec une marge à 12 pixels pour mieux vous rendre compte :

Limiter sa hauteur

Comme la marge la plus génante est celle du bas, on peux limiter la taille du control afin que cette marge se limite à la même marge.

<TextBlock Text="Hello"></TextBlock>
<Slider Height="75"/>
<TextBlock Text="Hello"></TextBlock>

Malheureusement le slider disparait au profit des marges.

Quand y en a marre

Ce qui est génial avec XAML c’est que même si un control ne fait pas ce que l’on aimerait faire (ou ce qu’il devrait), il y a souvent une solution du coté de son Template.

Avec Blend, j’édite donc le template par défaut du Slider afin de modifier ces marges qui nous ennuie.

<ControlTemplate x:Key="PhoneSimpleRepeatButton" TargetType="RepeatButton">
	<Rectangle Fill="Transparent"/>
</ControlTemplate>
<Style TargetType="Slider">
	<Setter Property="BorderThickness" Value="0"/>
	<Setter Property="BorderBrush" Value="Transparent"/>
	<Setter Property="Margin" Value="12"/>
	<Setter Property="Maximum" Value="10"/>
	<Setter Property="Minimum" Value="0"/>
	<Setter Property="Value" Value="0"/>
	<Setter Property="Background" Value="{StaticResource PhoneContrastBackgroundBrush}"/>
	<Setter Property="Foreground" Value="{StaticResource PhoneAccentBrush}"/>
	<Setter Property="Template">
		<Setter.Value>
			<ControlTemplate TargetType="Slider">
				<Grid Background="Transparent">
					<VisualStateManager.VisualStateGroups>
						<VisualStateGroup x:Name="CommonStates">
							<VisualState x:Name="Normal"/>
							<VisualState x:Name="MouseOver"/>
							<VisualState x:Name="Disabled">
								<Storyboard>
									<DoubleAnimation Duration="0" To="0.1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="HorizontalTrack"/>
									<DoubleAnimation Duration="0" To="0.1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="VerticalTrack"/>
									<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="HorizontalFill">
										<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>
									</ObjectAnimationUsingKeyFrames>
									<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="VerticalFill">
										<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>
									</ObjectAnimationUsingKeyFrames>
								</Storyboard>
							</VisualState>
						</VisualStateGroup>
					</VisualStateManager.VisualStateGroups>
					<Grid x:Name="HorizontalTemplate">
						<Grid.ColumnDefinitions>
							<ColumnDefinition Width="Auto"/>
							<ColumnDefinition Width="12"/>
							<ColumnDefinition Width="*"/>
						</Grid.ColumnDefinitions>
						<Rectangle x:Name="HorizontalFill" Fill="{TemplateBinding Foreground}" Height="12" IsHitTestVisible="False" Margin="0"/>
						<Rectangle x:Name="HorizontalTrack" Grid.Column="2" Fill="{TemplateBinding Background}" Height="12" IsHitTestVisible="False" Margin="0" Opacity="0.2"/>
						<RepeatButton x:Name="HorizontalTrackLargeChangeDecreaseRepeatButton" IsTabStop="False" Template="{StaticResource PhoneSimpleRepeatButton}"/>
						<RepeatButton x:Name="HorizontalTrackLargeChangeIncreaseRepeatButton" Grid.Column="2" IsTabStop="False" Template="{StaticResource PhoneSimpleRepeatButton}"/>
						<Thumb x:Name="HorizontalThumb" Grid.Column="1" Height="12" Margin="0" Width="12">
							<Thumb.Template>
								<ControlTemplate>
									<Canvas Background="{StaticResource PhoneForegroundBrush}" Height="12" Width="12">
										<Rectangle Fill="Transparent" IsHitTestVisible="True" Canvas.Left="-18" Canvas.Top="-18" Height="48" Width="48"/>
									</Canvas>
								</ControlTemplate>
							</Thumb.Template>
						</Thumb>
					</Grid>
					<Grid x:Name="VerticalTemplate">
						<Grid.RowDefinitions>
							<RowDefinition Height="*"/>
							<RowDefinition Height="12"/>
							<RowDefinition Height="Auto"/>
						</Grid.RowDefinitions>
						<Rectangle x:Name="VerticalFill" Fill="{TemplateBinding Foreground}" IsHitTestVisible="False" Margin="0" Grid.Row="2" Width="12"/>
						<Rectangle x:Name="VerticalTrack" Fill="{TemplateBinding Background}" IsHitTestVisible="False" Margin="0" Opacity="0.2" Width="12"/>
						<RepeatButton x:Name="VerticalTrackLargeChangeIncreaseRepeatButton" IsTabStop="False" Grid.Row="2" Template="{StaticResource PhoneSimpleRepeatButton}"/>
						<RepeatButton x:Name="VerticalTrackLargeChangeDecreaseRepeatButton" IsTabStop="False" Template="{StaticResource PhoneSimpleRepeatButton}"/>
						<Thumb x:Name="VerticalThumb" Height="12" Margin="18,0" Grid.Row="1" Width="12">
							<Thumb.Template>
								<ControlTemplate>
									<Canvas Background="{StaticResource PhoneForegroundBrush}" Height="12" Width="12">
										<Rectangle Fill="Transparent" Height="48" IsHitTestVisible="True" Canvas.Left="-18" Canvas.Top="-18" Width="48"/>
									</Canvas>
								</ControlTemplate>
							</Thumb.Template>
						</Thumb>
					</Grid>
				</Grid>
			</ControlTemplate>
		</Setter.Value>
	</Setter>
</Style>

Pour que la marge du contrôle soit complétement customisable j’ai modifié la taille du thumb (le bouton carrée qui permet de changer la valeur du slider en le faisant glisser) en le passant à 48 pixels.
Les marges des éléments HorizontalFill et HorizontalTrack (ainsi que leurs homologues Verticaux) ont été mise également à 0. Ces derniers étant responsables de la marge étrange que l’on obtenait auparavant.

Pour utiliser ce style il suffit de le glisser dans les ressources du fichier App.xaml par exemple et il s’appliquera à tous les Sliders de votre application.

Conclusion

Je me demande pourquoi cette marge en dur a été placée dans ce controle au lieu d’une gestion plus souple à base de Margin comme cela s’effectue habituellement.
Heureusement la souplesse de XAML permet de rectifier le tir et d’obtenir un contrôle plus facilement intégrable !

One Response to Positionner correctement le contrôle Slider

  1.  

leave your comment