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 :

Rafraichir un contrôle pendant un traitement


Sujet :

Windows Presentation Foundation

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut Rafraichir un contrôle pendant un traitement
    Hello !

    Je me suis décidé à me mettre au WPF et pour avoir qqch de concret à faire, je développe un jeu de yahtzee.

    J'ai donc affiché des images représentant les dés et je voudrais lors du click sur le bouton "Roll !" que les dés se mettent à jour (logique).

    Si c'est juste changer d'image, pas de souci. Le truc, c'est que je voudrais donner une impression de "roulement". Du coup, je fais une boucle dans laquelle je change l'image. Seulement, l'affichage ne se rafraichit que quand le traitement est terminé (à la fin de la boucle donc) et on ne voit donc le changement qu'une seule fois (au lieu de plusieurs fois très vite).

    Voici le code que j'ai produit pour cette partie :
    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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
        Private Sub btnRoll_Click(sender As System.Object, e As System.Windows.RoutedEventArgs)
            listDicesToRoll.Clear()
            For Each ctl As CheckBox In listDicesCheckbox
                If Not ctl.IsChecked Then
                    Select Case ctl.Name
                        Case "ckbDice1"
                            listDicesToRoll.Add(imgDice1)
                        Case "ckbDice2"
                            listDicesToRoll.Add(imgDice2)
                        Case "ckbDice3"
                            listDicesToRoll.Add(imgDice3)
                        Case "ckbDice4"
                            listDicesToRoll.Add(imgDice4)
                        Case "ckbDice5"
                            listDicesToRoll.Add(imgDice5)
                    End Select
                End If
            Next
            Dim x As Integer = 0
            Dim rnd As New Random()
            For i As Integer = 0 To 20
                For Each imgCtl As Image In listDicesToRoll
                    x = rnd.Next(5) + 1
                    Dim img As New BitmapImage
                    img.BeginInit()
                    img.UriSource = New Uri("Resources\de" & x.ToString & ".png", UriKind.Relative)
                    img.EndInit()
                    imgCtl.Source = img
                Next
                i += 1
            Next
            iRollsLeft -= 1
            If iRollsLeft <= 1 Then
                txtRolls.Text = CStr(iRollsLeft) & " roll left..."
                If iRollsLeft = 0 Then
                    btnRoll.IsEnabled = False
                End If
            Else
                txtRolls.Text = CStr(iRollsLeft) & " rolls left..."
            End If
        End Sub
    Ce n'est clairement pas parfait... Je chipote encore pas mal. Par exemple, pour les dés, au niveau visuel j'ai :

    - un stackpanel (nommé spDices) en orientation horizontal qui contient 5 fois :
    un stackpanel qui contient une image et une checkbox

    Comment parcourir avec une boucle for each les comboboxes contenues dans spDices ?

    Si je fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    For Each ctl as CheckBox in spDices.Children.OfType(Of CheckBox)()
    Forcément il ne trouve rien vu que les enfants sont des stackpanels... Bref, faut être récursif mais je n'avais pas envie de commencer à tester le type de l'enfant pour voir si je dois le parcourir aussi... Du coup, j'ai mis les checkboxes dans une liste et je parcours la liste... Une idée de comment améliorer cela ?

    Merci d'avance,

    Griftou.

  2. #2
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    Bonjour.

    Pour l'animation, tu fais ça sur le thread UI donc tu empêches les rafraîchissements. Il faut que tu utilises un DispatcherTimer (conseillé) ou que tu t'abonnes à CompositionTarget.Rendering (déconseillé dans ce cas puisque tu n'as que quelques étapes et que l'appli tourne au maximum de fps - jusqu'à 60 - tant que cet événement est souscrit). Ou, si tu veux ajouter des animations de fondu enchaîné entre les images pour ça un peu plus lisse, t'abonner à la fin des animations pour démarrer les suivantes.

    Concernant la recherche de descendants, tout passe par VisualTreeHelper. Voici quelques méthodes d'extension sympatoches :
    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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
            public static IEnumerable<Visual> Children(this Visual v)
            {
                int count = VisualTreeHelper.GetChildrenCount(v);
                for (int i = 0; i < count; i++)
                {
                    Visual child = VisualTreeHelper.GetChild(v, i) as Visual;
                    if (child != null) yield return child;
                }
            }
     
            public static IEnumerable<Visual> AncestorsAndSelf(this Visual v)
            {
                yield return v;
                for (Visual parent = v; parent != null; parent = VisualTreeHelper.GetParent(parent) as Visual)
                {
                    yield return parent;
                }
            }
     
            public static IEnumerable<Visual> Ancestors(this Visual v)
            {
                for (Visual parent = v; parent != null; parent = VisualTreeHelper.GetParent(parent) as Visual)
                {
                    yield return parent;
                }
            }
     
            public static IEnumerable<Visual> Descendants(this Visual v)
            {
                foreach (var child in Children(v))
                {
                    yield return child;
                    foreach (var descendant in Descendants(child))
                    {
                        yield return descendant;
                    }
                }
            }
     
            public static IEnumerable<Visual> DescendantsAndSelf(this Visual v)
            {
                yield return v;
     
                foreach (var child in Children(v))
                {
                    yield return child;
                    foreach (var descendant in Descendants(child))
                    {
                        yield return descendant;
                    }
                }
            }
     
            public static bool HasName(this Visual v, string name)
            {
                var element = v as FrameworkElement;
                if (element == null) return false;
                return element.Name == name;
            }
     
            public static IEnumerable<UIElement> AsEnumerable(this UIElementCollection c)
            {
                foreach (UIElement child in c)
                {
                    yield return child;
                }
            }
     
            public static IEnumerable<TResult> WhereAs<TResult>(this IEnumerable e)
                where TResult : class
            {
                foreach (var obj in e)
                {
                    TResult result = obj as TResult;
                    if (result != null) yield return result;
                }
            }
    Ce qui te permet de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    IEnumerable<Button> buttons = MyPanel.Descendants().WhereIs<Button>();

  3. #3
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut
    Ok alors j'ai été voir pour DispatcherTimer dans la msdn.

    Si je comprends bien son fonctionnement, cela crée un timer dont je peux utiliser l'évènement tick pour mettre à jour des éléments graphiques.

    Mais quand je regarde l'exemple donner, je ne vois pas du tout comment l'adapter à ma situation...

    Griftou.

  4. #4
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 197
    Par défaut
    pour info tu aurais eut le même problème en windows forms, un traitement long fige l'interface

    par contre tu es tombé dans le piège, il ne faut pas du tout coder en wpf comme en windows forms

    en théorie le code du window ne doit pas travailler sur les controles, il ne faut pratiquement pas en poser d'ailleurs, juste quelques conteneurs
    il faut plutot faire une classe dé, lier le checkbox à une instance de d par binding, et faire varier la valeur du dé, l'interface suivra
    (...)
    d'ailleurs il ne faut pas poser des checkbox et autres, il faut là aussi avoir une propriété "coché" sur le dé, et ne mettre que des dés (classe non graphique) dans la listbox et faire un datatemplate pour dire qu'un dé c'est un checkbox et une image, et que l'image varie selon la valeur

    après coté code, tu gères tes classes non graphiques, et tu peux directement les lires sans aller lire des checkbox et autres controles

    une fois que ca marche, tu précises au listbox que tu veux qu'il mettent les éléments en horizontal via un controltemplate dans itemspanel
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  5. #5
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut
    Ouch ! J'ai pas vu tout ça dans le tuto que j'ai suivi...

    T'aurais un exemple concret sous la main ? (pas forcément avec des dés évidemment)

    Comme ça je peux un peu voir la syntaxe de tout ça... Parce que chercher sur google quand on ne sait pas ce qu'on cherche, ce n'est pas pratique ^^

  6. #6
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut
    Article sur les datatemplates : http://www.wpftutorial.net/DataTemplates.html

    Perso, j'ai rien compris

    Il y a sûrement des prérequis que je ne possède pas encore :-/

Discussions similaires

  1. Redessiner contrôles HTML pendant un traitement javascript
    Par adaneels dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 19/07/2013, 10h58
  2. Réponses: 1
    Dernier message: 28/01/2006, 14h03
  3. [vb.net] Modification d'une winform pendant un traitement
    Par arnolem dans le forum Windows Forms
    Réponses: 4
    Dernier message: 25/11/2005, 18h16
  4. Activation d'un contrôle pendant 15s
    Par CCRNP dans le forum IHM
    Réponses: 3
    Dernier message: 30/01/2005, 13h19
  5. Rafraichissement de la fenetre pendant le traitement
    Par Bobx dans le forum Composants VCL
    Réponses: 5
    Dernier message: 20/02/2003, 15h13

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