IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Windows Presentation Foundation Discussion :

Masquer un élément en fonction de la valeur d'une propriété


Sujet :

Windows Presentation Foundation

  1. #1
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut Masquer un élément en fonction de la valeur d'une propriété
    Bonjour,

    pour masquer un élément si une propriété est "null" il est possible d'utiliser le "Style" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <local:ControlTest>
    	<local:ControlTest.Style>
    		<Style TargetType="local:ControlTest">
    			<Style.Triggers>
    				<DataTrigger Binding="{Binding Path=PropertyTest}" Value="{x:Null}">
    					<Setter Property="Visibility" Value="Collapsed" />
    				</DataTrigger>
    			</Style.Triggers>
    		</Style>
    	</local:ControlTest.Style>
    </local:ControlTest>
    Maintenant supposons qu'il existe un deuxième control du même type ou d'un autre qui doit aussi avoir un comportement similaire, on fait alors :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <local:OtherControlTest>
    	<local:OtherControlTest.Style>
    		<Style TargetType="local:OtherControlTest">
    			<Style.Triggers>
    				<DataTrigger Binding="{Binding Path=OtherPropertyTest}" Value="{x:Null}">
    					<Setter Property="Visibility" Value="Collapsed" />
    				</DataTrigger>
    			</Style.Triggers>
    		</Style>
    	</local:OtherControlTest.Style>
    </local:OtherControlTest>
    Et ainsi de suite, le code est dupliqué partout où le comportement "masqué si une propriété est null" est utilisé.


    Comment factoriser ce comportement ?


    Une possibilité semble être les propriétés attachées, mais est-il possible de les utiliser sans faire apparaitre d'élément supplémentaire dans le XAML, autre que la propriété sur les éléments cibles ?
    Ce qui donnerait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <local:ControlTest HideOnNull.Object="{Binding Path=PropertyTest}" >...

    Ou bien une solution plus lourde serait la création d'un conteneur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    <local:HideOnNull Object="{Binding Path=PropertyTest}">
    	<local:ControlTest>
    	...
    	</local:ControlTest>
    </local:HideOnNull>

    Quelles sont les solutions possibles, et laquelle vous parait la plus pertinente ?


    Merci.

  2. #2
    Membre régulier

    Étudiant
    Inscrit en
    Août 2004
    Messages
    108
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2004
    Messages : 108
    Points : 124
    Points
    124
    Par défaut
    Bonjour,

    Si j'ai bien compris ce que vous cherchez, la solution qui me parait être la plus pertinente est l'utilisation d'un dictionnaire de ressource global, contenant un style comme vous l'avez déjà écrit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    ...
    <Style TargetType="local:OtherControlTest">
    			<Style.Triggers>
    				<DataTrigger Binding="{Binding Path=OtherPropertyTest}" Value="{x:Null}">
    					<Setter Property="Visibility" Value="Collapsed" />
    				</DataTrigger>
    			</Style.Triggers>
    		</Style>
    </ResourceDictionary>
    Ainsi dans les fichier les xaml référençant le dictionnaire de ressources partagé tout les composant du type "local:OtherControlTest" auront le comportement souhaité sans rien écrire de plus.

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    La propriété attachée me semble une bonne solution, qui pourrait s'utiliser comme tu l'indiques.

    Le code devrait être un truc dans ce style :

    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    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
        public class HideOnNull
        {
     
            public static object GetObject(DependencyObject obj)
            {
                return (object)obj.GetValue(ObjectProperty);
            }
     
            public static void SetObject(DependencyObject obj, object value)
            {
                obj.SetValue(ObjectProperty, value);
            }
     
            // Using a DependencyProperty as the backing store for Object.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty ObjectProperty =
                DependencyProperty.RegisterAttached(
                    "Object",
                    typeof(object),
                    typeof(HideOnNull),
                    new UIPropertyMetadata(
                        null,
                        (obj, e) => 
                        {
                            UIElement uiElement = obj as UIElement;
                            if (uiElement != null)
                            {
                                if (e.NewValue == DependencyProperty.UnsetValue)
                                {
                                    // Si on efface la valeur de HideOnNull.Object, on remet la Visibility par défaut
                                    uiElement.ClearValue(UIElement.VisibilityProperty);
                                }
                                else if (e.NewValue == null)
                                {
                                    uiElement.Visibility = Visibility.Hidden;
                                }
                                else
                                {
                                    uiElement.Visibility = Visibility.Visible;
                                }
                            }
                        }));
     
        }

  4. #4
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    Merci de vos réponses.

    Tomlev ton implémentation fonctionne parfaitement, merci beaucoup.

  5. #5
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    Oups, en fait ça fonctionne parfaitement pour des valeur non "null" : le callback est bien invoqué et fait ce qu'il faut :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public static readonly DependencyProperty ObjectProperty =
                DependencyProperty.RegisterAttached("Object", typeof(object), typeof(CollapseIfNull), new UIPropertyMetadata(
                        null,
                        (obj, e) => 
                        {
                            UIElement uiElement = obj as UIElement;
                            if (uiElement != null)
                            {
                                if (e.NewValue == DependencyProperty.UnsetValue)
                                {
                                    uiElement.ClearValue(UIElement.VisibilityProperty);
                                }
                                else if (e.NewValue.Equals("123"))
                                {
                                    uiElement.Visibility = Visibility.Collapsed;
                                }
                                else
                                {
                                    uiElement.Visibility = Visibility.Visible;
                                }
                            }
                        }));
    et :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <local:UserControl1 local:CollapseIfNull.Object="123" />


    Mais dès que "Object" est "null" le callback n'est en fait pas invoqué du tout !
    Par exemple avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <local:UserControl1 local:CollapseIfNull.Object="{x:Null}" />

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    Ah ok... en fait c'est parce que null est la valeur initiale, donc quand tu affectes null ça ne provoque pas de DependencyPropertyChanged. Essaie d'enlever la valeur par défaut "null" dans le constructeur UIPropertyMetadata (laisse juste le callback). Ca devrait mettre comme valeur par défaut DependencyProperty.UnsetValue (soit pas de valeur), donc quand tu affecteras null le callback sera bien appelé

  7. #7
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    Merci encore c'est exactement le problème.

    Toutefois, sauf erreur, il ne semble pas possible de faire ignorer "null", même en utilisant le constructeur à un paramètre.

    En revanche spécifier "" comme valeur par défaut fait l'affaire puisqu'ici cette valeur n'a pas de sens si elle est spécifiée directement dans le XAML.
    De plus, et là c'est plus inattendu, si la valeur à laquelle est bindé "Object" est la chaine "", tout marche quand même comme il faut : il ne la considère pas comme la valeur par défaut.
    Il semble donc que cette notion de valeur par défaut soit spécifique au traitement du XAML.

    Est-ce plausible ?


    Quoiqu'il en soit encore un grand merci pour ton aide précieuse.

  8. #8
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    Citation Envoyé par seriousme Voir le message
    Est-ce plausible ?
    Euh... je sais pas

    Sinon, tu peux essayer de spécifier DependencyProperty.UnsetValue comme valeur par défaut, ce serait plus propre que ""

  9. #9
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    Cela provoque la levée d'une exception.

    Et ça semble confirmé par MSDN :
    Setting a DefaultValue of UnsetValue is specifically disallowed.
    http://msdn.microsoft.com/en-us/libr...nsetvalue.aspx

  10. #10
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    arf...
    ben faut mettre une valeur bidon alors... éventuellement d'une classe privée spécifiquement créée pour ça, histoire de pas interférer avec d'autres valeurs "réelles" possibles

  11. #11
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    Excellente astuce, ça semble fonctionner avec un "enum" "private" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    private enum DefaultValues
    {
        DefaultValue
    }
    Merci pour tout.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [XL-2010] Masquer des cellules en fonction de la valeur d'une autre cellule
    Par Azulnoth dans le forum Excel
    Réponses: 7
    Dernier message: 17/07/2014, 17h45
  2. Réponses: 1
    Dernier message: 19/07/2013, 12h08
  3. Réponses: 5
    Dernier message: 15/12/2009, 15h06
  4. Réponses: 1
    Dernier message: 23/04/2007, 10h13
  5. Réponses: 18
    Dernier message: 21/03/2006, 13h46

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo