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 :

[WPF]Références partagé entre un Contrôle et une liste


Sujet :

Windows Presentation Foundation

  1. #1
    Membre du Club
    Inscrit en
    Octobre 2010
    Messages
    205
    Détails du profil
    Informations forums :
    Inscription : Octobre 2010
    Messages : 205
    Points : 66
    Points
    66
    Par défaut [WPF]Références partagé entre un Contrôle et une liste
    Bonjour,

    Voila j'ai créé un UniformGrid comme ceci:
    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
     
    zones = new List<AirportZone>( Rows * Columns );
     
                for ( int j = 0; j < Rows; ++j )
                {
                    for ( int i = 0; i < Columns; ++i )
                    {
                        AirportZone zone = new AirportZone( new Point( i, j ),
                                                            String.Empty,
                                                            false );
                        zones.Add( zone );
                        SetEventsToZone( zone );
                        Children.Add( zone );
                    }
                }
     
                UpdateLayout( );
    Quand je modifie une "zone" dans la liste, celle-ci n'est pas modifié dans Children, pourquoi?

    Voici un exemple de modification:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
                    zones[ index ].IsBuilt = true;

  2. #2
    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 : 37
    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
    C'est parce que le container de la zone n'est pas notifié du changement, même si "AirportZone" implémente INotifyPropertyChanged.

    Tu vas sans doute être obligé de gérer la notification toi-même;
    une solution pas très élégante serait d'utiliser une ObservableCollection à la place d'une List et de retirer puis réajouter tout élément modifié.
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  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 749
    Points
    39 749
    Par défaut
    Ta classe AirportZone doit implémenter INotifyPropertyChanged, pour notifier l'interface graphique quand une propriété est modifiée. Sinon le binding n'a aucun moyen de savoir que quelque chose a changé...

  4. #4
    Membre du Club
    Inscrit en
    Octobre 2010
    Messages
    205
    Détails du profil
    Informations forums :
    Inscription : Octobre 2010
    Messages : 205
    Points : 66
    Points
    66
    Par défaut
    Ah d'accord, bah j'ai fait ce que tu m'as dit en utilisant l'interface INotifyPropertyChanged, mais ça ne marche pas, je ne dois pas binder manuellement mon conteneur parent (UniformGrid) avec la liste en question?

  5. #5
    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 749
    Points
    39 749
    Par défaut
    Il faudrait que tu donnes plus d'informations... tu en fais quoi de ta liste de zones exactement ? Et comment as-tu implémenté INotifyPropertyChanged ?

  6. #6
    Membre du Club
    Inscrit en
    Octobre 2010
    Messages
    205
    Détails du profil
    Informations forums :
    Inscription : Octobre 2010
    Messages : 205
    Points : 66
    Points
    66
    Par défaut
    J'ai un uniformGrid de AirportZone et une liste de AirportZone aussi. J'ai choisi d'avoir une List de AirportZone pour faciliter l'utilisation dans une application extérieur, c'est plus agréable d'utiliser une List qu'une UICollection... (Point de vue personnel)

    Voici comment j'ai implémenté la méthode:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    private void NotifyPropertyChanged( String info )
    {
                if ( PropertyChanged != null )
                {
                    PropertyChanged( this, new PropertyChangedEventArgs( info ) );
                }
    }
    Je l'ai écri dans une méthode pour faciliter alléger le code...

    Un exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
     
                        NotifyPropertyChanged( "BackgroundImage" );

  7. #7
    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 749
    Points
    39 749
    Par défaut
    OK, mais comment tu fais pour afficher tes AirportZone ? Avec un DataTemplate ?

  8. #8
    Membre du Club
    Inscrit en
    Octobre 2010
    Messages
    205
    Détails du profil
    Informations forums :
    Inscription : Octobre 2010
    Messages : 205
    Points : 66
    Points
    66
    Par défaut
    Non, tout simplement avec la méthode OnRender:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
            protected override void OnRender( System.Windows.Media.DrawingContext drawingContext )
            {
                drawingContext.DrawRectangle( Brushes.White, new Pen( BorderBrush, 0.2 ),
                                              new Rect( RenderSize ) );
            }

  9. #9
    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 749
    Points
    39 749
    Par défaut
    Citation Envoyé par Babas007 Voir le message
    Non, tout simplement avec la méthode OnRender:
    Ah ok... on n'a pas la même notion de "simplement"

    Dans ce cas c'est normal que les modifs soient pas prises en compte automatiquement, il faut gérer manuellement le fait de redessiner quand une propriété change.

    Par contre, dans ce code je vois pas où tu prends en compte les propriétés de AirportZone ?

  10. #10
    Membre du Club
    Inscrit en
    Octobre 2010
    Messages
    205
    Détails du profil
    Informations forums :
    Inscription : Octobre 2010
    Messages : 205
    Points : 66
    Points
    66
    Par défaut
    Voici un exemple, quand je modifie l'image de la zone je veux que ça modifie l'image dans le contrôle parent aussi:
    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
            public string BackgroundImage
            {
                get
                {
                    return Content != null
                           ? ( Content as Image ).Source.ToString( )
                           : String.Empty;
                }
                set
                {
                    if ( value != String.Empty )
                    {
                        Content = new Image
                        {
                            Source = new BitmapImage( new Uri( value ) )
                        };
     
                        NotifyPropertyChanged( "BackgroundImage" );
                    }
                }
            }
    Mais quel est le rapport avec l'affichage, je comprends pas trop, ça m'a l'air en tout cas plus compliqué que je le pensais cette histoire...

  11. #11
    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 749
    Points
    39 749
    Par défaut
    Citation Envoyé par Babas007 Voir le message
    Mais quel est le rapport avec l'affichage
    C'est moi qui ai supposé (à tort visiblement) que c'était un problème d'affichage, à cause de ta phrase dans le premier post :

    Quand je modifie une "zone" dans la liste, celle-ci n'est pas modifié dans Children, pourquoi?
    Vu que les deux collections contiennent les mêmes instances de AirportZone, ce que tu dis n'est pas possible (*), et donc j'ai cru que tu voulais dire que tu ne voyais pas la modification à l'affichage.

    Qu'est-ce qui te fait dire que ce n'est pas modifié dans Children ? Tu as vérifié le contenu de la liste ?

    (*) ce serait possible si AirportZone était un type valeur, mais ce n'est pas le cas, sinon zones[ index ].IsBuilt = true; génèrerait une erreur de compilation

  12. #12
    Membre du Club
    Inscrit en
    Octobre 2010
    Messages
    205
    Détails du profil
    Informations forums :
    Inscription : Octobre 2010
    Messages : 205
    Points : 66
    Points
    66
    Par défaut
    Oui en effet, t'as raison, c'est un problème d'affichage...Je suis resté bloqué sur mon OnRender...Anyway, je comprends je viens de refaire un test, donc oui si je modifie une zone elle est modifiée dans la liste ainsi que dans la collection Children...J'étais persuadé que ça ne marchait pas tout le temps...Donc dans ce cas là, je n'ai qu'à forcer le réaffichage des enfants nan?

  13. #13
    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 749
    Points
    39 749
    Par défaut
    Citation Envoyé par Babas007 Voir le message
    Donc dans ce cas là, je n'ai qu'à forcer le réaffichage des enfants nan?
    A priori, oui

    Mais je maintiens tu te serais beaucoup moins pris la tête avec un template...

  14. #14
    Membre du Club
    Inscrit en
    Octobre 2010
    Messages
    205
    Détails du profil
    Informations forums :
    Inscription : Octobre 2010
    Messages : 205
    Points : 66
    Points
    66
    Par défaut
    Vas y, je t'écoute, je n'ai pas dit que ma solution était la meilleur.
    Si tu penses que c'est plus simple, je suis tout ouie!
    Ca m'arrangerai encore plus si ça me permettait d'avoir un code peu plus clean que ce que j'ai actuellement...

  15. #15
    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 749
    Points
    39 749
    Par défaut
    Ben le fait de faire le rendu du contrôle dans OnRender, c'est une pratique héritée de Winforms, où il n'y avait pas d'autre solution que d'implémenter OnPaint (ou gérer l'évènement Paint).

    En WPF, un contrôle n'a pas d'apparence propre (on dit que les contrôles sont "lookless"). Son apparence est basée sur un ControlTemplate (bien sûr, tous les contrôles on un template par défaut, défini dans le style par défaut). De cette façon il est toujours possible de redéfinir l'apparence d'un contrôle. Autres avantages non négligeables :
    - pas besoin de se taper le dessin à la main, tu définis ton interface en XAML, ce qui est quand même beaucoup plus facile
    - tu peux profiter du binding pour ne pas avoir à gérer le rafraichissement à la main

    Le principe est le suivant :

    - tu overrides la propriété DefaultStyleKey (clé du style par défaut) dans le constructeur statique de ton contrôle :

    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    static AirportZone()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(AirportZone), new FrameworkPropertyMetadata(typeof(AirportZone)));
    }

    - tu définis un style par défaut pour ton contrôle avec cette clé, et dans le style tu définis le template. Si tu as besoin de te binder sur une propriété du contrôle, tu utilises {TemplateBinding}.

    Exemple bidon (vu que je sais pas du tout à quoi doit ressembler ton contrôle) :

    Code XML : 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
    <Style x:Key="{x:Type my:AirportZone}" TargetType="{x:Type my:AirportZone}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type my:AirportZone}">
                    <Border BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            CornerRadius="3">
                        <Border.Background>
                            <ImageBrush ImageSource="{TemplateBinding BackgroundImage}" />
                        </Border.Background>
                        <TextBlock Text="{TemplateBinding ZoneName}" />
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    Je vais pas trop rentrer dans les détails, mais tu devrais trouver des tutoriels un peu partout sur le sujet (en voilà déjà un). Regarde aussi la doc de la classe ControlTemplate, ils expliquent pas mal de trucs

  16. #16
    Membre du Club
    Inscrit en
    Octobre 2010
    Messages
    205
    Détails du profil
    Informations forums :
    Inscription : Octobre 2010
    Messages : 205
    Points : 66
    Points
    66
    Par défaut
    Ahhh très intéressant!!!
    Mais est ce que cela va résoudre le problème? Car là c'est un excellent exemple pour mon AirportZone, mais en fait j'ai un autre contrôle qui s'appelle donc AiportArea, composé de plusieurs AirportZone (Children). Donc si je modifie un AirportZone dans ma liste, est-ce ce code suffira-t-il pour voir la modification directement dans ma vue "AirportArea"? (en y ajoutant l'implémentation de l'interface INotifyPropertyChanged)

  17. #17
    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 749
    Points
    39 749
    Par défaut
    Citation Envoyé par Babas007 Voir le message
    Ahhh très intéressant!!!
    Mais est ce que cela va résoudre le problème? Car là c'est un excellent exemple pour mon AirportZone, mais en fait j'ai un autre contrôle qui s'appelle donc AiportArea, composé de plusieurs AirportZone (Children). Donc si je modifie un AirportZone dans ma liste, est-ce ce code suffira-t-il pour voir la modification directement dans ma vue "AirportArea"? (en y ajoutant l'implémentation de l'interface INotifyPropertyChanged)
    Oui, le contrôle AirportZone se mettra à jour, peu importe qu'il soit dans un AirportArea ou ailleurs.

  18. #18
    Membre du Club
    Inscrit en
    Octobre 2010
    Messages
    205
    Détails du profil
    Informations forums :
    Inscription : Octobre 2010
    Messages : 205
    Points : 66
    Points
    66
    Par défaut
    Re!

    Désolé, pas mal occupé ces derniers temps... Donc j'ai gardé la solution OnRender depuis, mais je voudrais utilisé ce que tu me dis. Tout d'abord, dans quel type de control je dois créer ça? UserControl ou CustomControl? je suis dans une solution Library et je ne peux pas utiliser CustomControl, de plus qu'est ce que style, template, controltemplate...Je suis un peu perdu avec tout ces termes...

    Cordialement,

  19. #19
    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 749
    Points
    39 749
    Par défaut
    Citation Envoyé par Babas007 Voir le message
    Tout d'abord, dans quel type de control je dois créer ça? UserControl ou CustomControl?
    Custom control

    Citation Envoyé par Babas007 Voir le message
    je suis dans une solution Library et je ne peux pas utiliser CustomControl
    Tu as créé le projet comment ? normalement il faut le créer comme bibliothèque de contrôles WPF. Il me semble que dans une simple "bibliothèque de classes" il te propose pas custom control... Je sais pas trop si on peut changer le type d'un projet sans le recréer

    Citation Envoyé par Babas007 Voir le message
    de plus qu'est ce que style, template, controltemplate...Je suis un peu perdu avec tout ces termes...
    Ben je peux pas vraiment te l'expliquer en 2 minutes, il y a trop de choses à dire... regarde dans un tuto ou un bouquin.

Discussions similaires

  1. Réduire l'espace entre un titre et une liste
    Par Akazed dans le forum Mise en page CSS
    Réponses: 7
    Dernier message: 18/02/2010, 10h08
  2. [Rendering] Création d'un contrôle ayant une liste
    Par Woufeigh dans le forum Windows Forms
    Réponses: 0
    Dernier message: 29/03/2009, 21h15
  3. Lien entre deux colonnes dans une liste (utilisation de combobox)
    Par cantanna1988 dans le forum SharePoint
    Réponses: 7
    Dernier message: 02/03/2009, 17h10
  4. Réponses: 4
    Dernier message: 26/02/2009, 16h58
  5. Réponses: 1
    Dernier message: 18/04/2007, 11h14

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