Accueil

L'OpacityMask en XAML

by Jean-Camille Mercier 20. avril 2016 16:34

J'ai besoin de faire un truc tout simple : un bouton image qui est bleu lorsqu'il est actif et gris lorsqu'il est désactivé.

Pour être malin, on va utiliser le principe de la ICommand bindée sur un bouton, ainsi, lorsque le CanExecute() retournera false, le bouton sera désactivé. Ensuite on va supprimer entièrement le template du bouton et y placer notre image blanche en OpacityMask d'un rectangle sur lequel on pourra faire varier la couleur du Fill et ainsi coloriser l'image. Pour finir, il reste juste à binder Fill à IsEnabled du bouton.

1- Rappel de la syntaxe de la commande MVVM light :

public ICommand AddCommand { get; private set; }

public Ctor()
{
    this.AddCommand = new RelayCommand(this.AddVersion, this.AddVersionCanExecute);
}

private void AddVersion()
{
    // Truc à faire
}
private bool AddVersionCanExecute()
{
    // Peut-on faire le truc ?
    return this.SelectedVersion != null;
}

2- Code XAML :

<!--Image button : no template, hand cursor-->
<Style x:Key="btImg" TargetType="Button">
    <Setter Property="Template" Value="{x:Null}" />
    <Setter Property="Cursor" Value="Hand" />
    <Setter Property="VerticalAlignment" Value="Center" />
</Style>

<!--L'image blanche-->
<ImageBrush x:Key="AddVipIcon" ImageSource="/Mon.Assembly;component/Images/add.png" />

<!--La jolie couleur bleue-->     
<SolidColorBrush x:Name="c_blue" Color="#3572BA" />       
           
<!--Le Converter-->
<fwk:BooleanConverter x:Key="CanAddToColorConv" 
                      TrueValue="{StaticResource c_blue}" FalseValue="Gray" />
                
<!-- Et enfin le bouton -->    
<Button Style="{StaticResource btImg}" Command="{Binding AddCommand}">
    <!-- Le rectangle donne la couleur à l'image blanche en opacity mask -->
    <!-- Le bouton gère son IsEnabled avec le CanExecute de la commande -->
    <!-- Le converter sur Fill donne la couleur en fontion du IsEnabled : -->
    <!-- actif = bleu / désactivé = gris -->
    <Rectangle Width="16" Height="16" OpacityMask="{StaticResource AddVipIcon}"
               Fill="{Binding IsEnabled, 
                      RelativeSource={RelativeSource AncestorType=Button}, 
                      Converter={StaticResource CanAddToColorConv}}"/>
</Button>

 

J'aime bien ce code car il utilise au maximum la puissance du XAML et on trouve des rappels intéressants comme le findAncestor sur le type ou l'imageBrush