none
GridView: Comment désactiver le retour graphique d'un clic ? RRS feed

  • Question

  • Bonjour,

    Dans un GridView comment désactiver le retour graphique qui est généré
    quand on clic sur certain items ?

     
    Dans mon cas, certain items sont “cliquables” et d’autre items de la même
    liste sont désactivés.
     

    Je voudrai supprimer pour les items désactivé le clic mais surtout le
    retour graphique qui est générer quand on clique dessus.

    Merci.

    J'ai le code suivant :

            <GridView
                x:Name="itemGridView"
                AutomationProperties.AutomationId="ItemsGridView"
                AutomationProperties.Name="Items"
                TabIndex="1"
                Grid.RowSpan="2"
                Padding="116,136,116,46"
                ItemsSource="{Binding ListeCompte}"
                ItemTemplate="{StaticResource DataTemplateRacineKey}"
                SelectionMode="None"
                IsSwipeEnabled="false"
                IsItemClickEnabled="True"
                ItemClick="itemGridView_ItemClick_1">
            </GridView>

    mercredi 6 mars 2013 19:44

Réponses

  • Bonjour,

    Youpi ça marche !

    Vos indications et ce blogue m’ont aidé. Merci a vous.
    http://vikingco.de/gridviewsucks.html

    Je résume comment j’ai fait.

    1. Commencer par créer deux styles.

        - Un style pour les éléments actifs (cliquable). C’est le style par défaut récupéré avec Blend.
        - Un style pour les éléments inactifs (non cliquable) Pour ce deuxième style j’ai juste mis en commentaire les VisualState “Pressed” et “PointerOverPressed”

    2. Il faut créer une classe qui hérite de StyleSelector.
        Une instance de cette classe sera assignée à la propriété ItemContainerStyleSelector du GridView.
        Elle permet le choix d’un style.

        Dans cette classe on va ajouter deux propriétés de type Style.
       
            - Une qui recevra le style actif que j’ai nommé ActifTemplate
            - Une autre pour le style inactif que j’ai nommé InactifTemplate

        On va surcharger ensuite la procédure SelectStyleCore.
        Cette procédure permet de choisir le style à appliquer item par item. Elle reçoit en paramètre l’élément en cours d’affichage.
        Il suffit de tester l’item reçu en paramètre et de renvoyer le bon style

    class ItemContainerStyleCompteSelector : StyleSelector
    {
        public Style ActifTemplate { get; set; }
        public Style InactifTemplate { get; set; }
    
        protected override Style SelectStyleCore(object item, DependencyObject container)
        {            
            if (item is CompteClass)
            {
                Boolean aDesEnfants = ((CompteClass)item).ADesEnfants;
                if (aDesEnfants)
                {
                    return ActifTemplate;
                }
                else
                {
                    return InactifTemplate;
                }
            }
            else
            {
                return base.SelectStyleCore(item, container);
            }
        }
    }

    3. Retour dans les ressources de l’application pour créer une instance de cette classe.

    Je ne connaissais pas mais on peut affecter ici directement les styles actif et inactif aux deux propriétés définies précédemment dans la classe.
    Il parait que c’est plus propre que de fouiller dans les ressources comme j’ai fait avec mon convertisseur. (cf. plus haut dans le post)

    <conv:ItemContainerStyleCompteSelector x:Key="ItemContainerStyleCompteSelectorKey" 
                                           ActifTemplate="{StaticResource StyleCompteActifKey}" 
                                           InactifTemplate="{StaticResource StyleCompteInactifKey}">        
    </conv:ItemContainerStyleCompteSelector>

    4. Et en dernier on va utiliser cette ressource dans le GridView.

    ItemContainerStyleSelector="{StaticResource ItemContainerStyleCompteSelectorKey}"

    <GridView
        x:Name="itemGridView"
        AutomationProperties.AutomationId="ItemsGridView"
        AutomationProperties.Name="Items"                        
        TabIndex="1"
        Grid.RowSpan="2"
        Padding="116,136,116,46"
        ItemsSource="{Binding ListeCompte}"
        ItemTemplate="{StaticResource DataTemplateFullStyleKey}"    
        ItemContainerStyleSelector="{StaticResource ItemContainerStyleCompteSelectorKey}"
        SelectionMode="None"
        IsSwipeEnabled="false"
        IsItemClickEnabled="True"
        ItemClick="itemGridView_ItemClick_1" >
    </GridView>

    Remarque j’ai lu sur plusieurs sites que l’utilisation du ItemTemplate conjointement au ItemContainerStyleSelector ne fonctionnait pas et qu’il fallait choisir entre l’un ou l’autre.
    Pour moi ça marche pourtant. C’est bien possible qu’il y ai pas mal de confusion car tous cela n’est quand même pas si simple.
    En tout cas merci pour le coup de main car ça marche et j’ai fais un pas de plus dans l’apprentissage de tout ces “Machins” !



    lundi 11 mars 2013 22:21

Toutes les réponses

  • Bonjour,

    tu peux désactiver les animations de chaque état en modifiant le ItemContainerStyle avec Blend, en revanche j'ai peur que malheureusement ce soit applicable à tous les éléments de la liste.

    Si quelqu'un a une solution technique pour choisir le style du container suivant les items, un peu comme un DataTemplateSelector.... mais je ne sais pas si ca existe 


    #codingwithfun / .NET

    • Proposé comme réponse Aurel Bera vendredi 8 mars 2013 14:10
    mercredi 6 mars 2013 20:28
  • Ça me parait un peu compliqué car je ne suis pas un pro de Blend.

    Mais ça ressemble aux genres de solutions que j'ai vu. C'est à dire copier le style par défaut et le recréer sans les animations. Ensuite l'appliquer sur les éléments désactivés.

    Je vais essayer de faire comme ça mais ce n'est pas gagné...

    jeudi 7 mars 2013 20:41
  • J'ai trouvé un début de solution

    1 Extraire le style avec Blend.

    On ouvre Blend en faisant Menu Afficher->Ouvrir dans Blend.

    Puis on sélectionne le GridView et on extrait le style du ItemContainerStyle.

    Ensuite on enregistre la copie et le fichier.

    2. De retour dans VS2012 on retrouve le style.

    Je ne mets pas tout le style, il est long. Il commence par :

            <Style x:Key="GridViewItemStyle2" TargetType="GridViewItem">
                <Setter Property="FontFamily" Value="{StaticResource ContentControlThemeFontFamily}"/>
                <Setter Property="FontSize" Value="{StaticResource ControlContentThemeFontSize}"/>
                <Setter Property="Background" Value="Transparent"/>

    et puis un peut plus loin dans le style on trouve la partie qui concerne le clic (Pressed)

    <VisualState x:Name="Pressed">
    	<Storyboard>
    		<PointerDownThemeAnimation TargetName="ContentContainer"/>
    	</Storyboard>
    </VisualState>
    <VisualState x:Name="PointerOverPressed">
    	<Storyboard>
    		<PointerDownThemeAnimation TargetName="ContentContainer"/>
    		<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PointerOverBorder"/>
    		<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="SelectionBackground">
    			<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ListViewItemSelectedPointerOverBackgroundThemeBrush}"/>
    		</ObjectAnimationUsingKeyFrames>
    		<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Stroke" Storyboard.TargetName="SelectedBorder">
    			<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ListViewItemSelectedPointerOverBorderThemeBrush}"/>
    		</ObjectAnimationUsingKeyFrames>
    		<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="SelectedEarmark">
    			<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ListViewItemSelectedPointerOverBackgroundThemeBrush}"/>
    		</ObjectAnimationUsingKeyFrames>
    		</Storyboard>
    </VisualState>

    3. Modifier le syle

    J'ai tout simplement supprimer les appels aux storyboard.

    Ce qui donne :

    <VisualState x:Name="Pressed">
    </VisualState>
    <VisualState x:Name="PointerOverPressed">
    </VisualState>

    4. Relier ce nouveau style au ItemContainerStyle du GridView.

    De cette façon :

            <GridView
                x:Name="itemGridView"
    ...
                ItemContainerStyle="{StaticResource GridViewItemStyle2}"
    ...
            ></GridView>

    Maintenant quand je clic sur les élements du GridView je n'ai plus de retrour graphique.

    Il ne me reste plus qu'a trouver comment faire pour n'appliquer ce style qu'aux éléments désactivés de la grille.




    vendredi 8 mars 2013 22:43
  • Le probléme du ListContainerStyle, c'est qu'il va s'affecter à TOUS les items et je ne crois pas qu'il y ai une solution pour permettre de choisir les éléments désactivés (pour ton exemple). Comme le disais Sébastien Pertus, la meilleure solution est surement de faire ce que tu viens de faire mais en faisant 2 styles différents et en affectant le bon style suivant la valeur qui te permet de savoir si ton item est désactivé ou pas. Je ferais ça en Code-Behind pour ma part, ne voyant pas comment faire cela en XAML,  mais si quelqu'un sait je suis preneur de la solution également.

    #codingwithfun / .NET

    vendredi 8 mars 2013 23:05
  • Avant de continuer j’ai voulu réutiliser ce que je connaissais car j'ai
    fait quelque chose de similaire mais pour le ItemTemplate.

    Avec un convertisseur j’arrive à faire en sorte que le DataTemplate
    des Items s’adapte en fonction d’une des propriétés de l’élément affiché.
    Chacun de mes éléments possède un niveau. Pour faire simple, les éléments
    de niveau 1 sont affichés d’un certaine façon (dans un grands carré) et les
    éléments des autres niveau d’une autre façon (dans un petit carré).
    On peut même mélangés des éléments de différent niveaux l’affichage change
    pour chaque éléments.
    Je ne sais pas si c’est une bonne façon de faire mais c’est une technique
    qui marche.
     

    En gros ç’est codé comme ça :

    <GridView>
    ...
    ItemTemplate="{StaticResource DataTemplateFullStyleKey}"
    ...
    </GridView>

    Avec dans mes styles

        <DataTemplate x:Key="DataTemplateFullStyleKey">
            <ContentPresenter ContentTemplate="{Binding Converter={StaticResource compteToStyleConverterKey}}" Content="{Binding}"/>
        </DataTemplate>

    Et pour le convertisseur

    // Niveau 1
    return (DataTemplate)App.Current.Resources["Standard250x250ItemTemplateKey"];
    // Autres niveaux
    return (DataTemplate)App.Current.Resources["Standard130ItemTemplateKey"];

    J'ai donc idée de réutiliser cela pour le ItemContainerStyle.

    Dans le style d’origine du GridView on a un storyboard pour VisualState "Pressed".

    <VisualState x:Name="Pressed">
        <Storyboard>
            <PointerDownThemeAnimation TargetName="ContentContainer"/>
        </Storyboard>
    </VisualState>

    L’idée est de modifier dans le style du GridView le storyboars du
    VisualState "Pressed".

    Pour les élément actifs je veux garder le storyboard mais pour les éléments
    inactifs le storyboard serai vide ou null (a voir).
     
    Mais avant d’aller plus loin j'ai simplement voulu tester l'affectation
    d'une StaticResource sur le storyboard du VisualState
     

    J'ai transformé dans le style du GridView le VisualState "Pressed" et mis le storybard en tant que StaticResource  

    <VisualState x:Name="Pressed" Storyboard="{StaticResource PressedStoryboardKey}">
    
    <Storyboard x:Key="PressedStoryboardKey">
        <PointerDownThemeAnimation TargetName="ContentContainer"/>
    </Storyboard>

    et au niveau du GridView

    <GridView>
    ...
    ItemContainerStyle="{StaticResource GridViewItemStyleKey}"
    ...
    </GridView>

    Pffff !

    Cela génère un jolie plantage au lancement de l'appli !

     

    Message = "Failed to assign to property 'Windows.UI.Xaml.VisualState.Storyboard'. [Line: 164 Position: 74]"

    Question : Peut-on utiliser un storyboard en StaticResource ?

    Bon maintenant je vais regarder comment utiliser ce fameux ItemTemplateSelector ...







    samedi 9 mars 2013 21:46
  • Concernant l'ItemTemplateSelector, c'est grosso-modo le mécanisme que tu as mis en place avec ton Converter qui te renvoi un DataTemplate. Pour l'ItemTemplateSelector tu va définir une classe qui fait grosso-modo la même chose que ton Converter.

    pour le StoryBoard en StaticResource, je ne sais pas je n'ai jamais essayé.


    #codingwithfun / .NET

    samedi 9 mars 2013 23:40
  • Bonjour,

    Youpi ça marche !

    Vos indications et ce blogue m’ont aidé. Merci a vous.
    http://vikingco.de/gridviewsucks.html

    Je résume comment j’ai fait.

    1. Commencer par créer deux styles.

        - Un style pour les éléments actifs (cliquable). C’est le style par défaut récupéré avec Blend.
        - Un style pour les éléments inactifs (non cliquable) Pour ce deuxième style j’ai juste mis en commentaire les VisualState “Pressed” et “PointerOverPressed”

    2. Il faut créer une classe qui hérite de StyleSelector.
        Une instance de cette classe sera assignée à la propriété ItemContainerStyleSelector du GridView.
        Elle permet le choix d’un style.

        Dans cette classe on va ajouter deux propriétés de type Style.
       
            - Une qui recevra le style actif que j’ai nommé ActifTemplate
            - Une autre pour le style inactif que j’ai nommé InactifTemplate

        On va surcharger ensuite la procédure SelectStyleCore.
        Cette procédure permet de choisir le style à appliquer item par item. Elle reçoit en paramètre l’élément en cours d’affichage.
        Il suffit de tester l’item reçu en paramètre et de renvoyer le bon style

    class ItemContainerStyleCompteSelector : StyleSelector
    {
        public Style ActifTemplate { get; set; }
        public Style InactifTemplate { get; set; }
    
        protected override Style SelectStyleCore(object item, DependencyObject container)
        {            
            if (item is CompteClass)
            {
                Boolean aDesEnfants = ((CompteClass)item).ADesEnfants;
                if (aDesEnfants)
                {
                    return ActifTemplate;
                }
                else
                {
                    return InactifTemplate;
                }
            }
            else
            {
                return base.SelectStyleCore(item, container);
            }
        }
    }

    3. Retour dans les ressources de l’application pour créer une instance de cette classe.

    Je ne connaissais pas mais on peut affecter ici directement les styles actif et inactif aux deux propriétés définies précédemment dans la classe.
    Il parait que c’est plus propre que de fouiller dans les ressources comme j’ai fait avec mon convertisseur. (cf. plus haut dans le post)

    <conv:ItemContainerStyleCompteSelector x:Key="ItemContainerStyleCompteSelectorKey" 
                                           ActifTemplate="{StaticResource StyleCompteActifKey}" 
                                           InactifTemplate="{StaticResource StyleCompteInactifKey}">        
    </conv:ItemContainerStyleCompteSelector>

    4. Et en dernier on va utiliser cette ressource dans le GridView.

    ItemContainerStyleSelector="{StaticResource ItemContainerStyleCompteSelectorKey}"

    <GridView
        x:Name="itemGridView"
        AutomationProperties.AutomationId="ItemsGridView"
        AutomationProperties.Name="Items"                        
        TabIndex="1"
        Grid.RowSpan="2"
        Padding="116,136,116,46"
        ItemsSource="{Binding ListeCompte}"
        ItemTemplate="{StaticResource DataTemplateFullStyleKey}"    
        ItemContainerStyleSelector="{StaticResource ItemContainerStyleCompteSelectorKey}"
        SelectionMode="None"
        IsSwipeEnabled="false"
        IsItemClickEnabled="True"
        ItemClick="itemGridView_ItemClick_1" >
    </GridView>

    Remarque j’ai lu sur plusieurs sites que l’utilisation du ItemTemplate conjointement au ItemContainerStyleSelector ne fonctionnait pas et qu’il fallait choisir entre l’un ou l’autre.
    Pour moi ça marche pourtant. C’est bien possible qu’il y ai pas mal de confusion car tous cela n’est quand même pas si simple.
    En tout cas merci pour le coup de main car ça marche et j’ai fais un pas de plus dans l’apprentissage de tout ces “Machins” !



    lundi 11 mars 2013 22:21