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

Silverlight Discussion :

Affichage d'un calendrier - DataBinding et ItemsControl


Sujet :

Silverlight

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Invité
    Invité(e)
    Par défaut Affichage d'un calendrier - DataBinding et ItemsControl
    Bonjour à tous,

    Je fais appel à votre aide pour m'aider sur un "problème" que je rencontre actuellement dans le cadre d'un développement.

    Pour situer le contexte, je reçois une liste d'objet (via un service WCF) qui me permet d'alimenter un planning.

    Je précise tout de suite que j'ai la main sur les deux parties (interface graphique et service WCF), j'ai donc la possibilité de modifier le format
    des éléments de la liste qui permet d'afficher le planning.

    Actuellement, chaque élément de la liste contient 3 propriétés :
    Date
    DispoMatin
    DispoApresMidi

    DispoMatin et DispoApresMidi sont de type Booleen et j'ai donc un "enregistrement" par jour. Ce qui fait que la liste contient 6 éléments de type Planning au final (du lundi au samedi).

    Lors de mes premiers tests, j'ai créé une interface graphique trés rapidement et de manière assez simpliste :

    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
    <Button x:Name="LuMAT" Width="80" Height="70" Style="{StaticResource styleBoutonPlanning}"
    Grid.Row="1" Grid.Column="0" Foreground="Red" FontWeight="Bold" />
    <Button x:Name="LuAM" Width="80" Height="70" Style="{StaticResource styleBoutonPlanning}"
    Grid.Row="2" Grid.Column="0" Foreground="Red" FontWeight="Bold" />
     
    <Button x:Name="MaMAT" Width="80" Height="70" Style="{StaticResource styleBoutonPlanning}"
    Grid.Row="1" Grid.Column="1" Foreground="Red" FontWeight="Bold" />
    <Button x:Name="MaAM" Width="80" Height="70" Style="{StaticResource styleBoutonPlanning}"
    Grid.Row="2" Grid.Column="1" Foreground="Red" FontWeight="Bold" />
     
    <Button x:Name="MeMAT" Width="80" Height="70" Style="{StaticResource styleBoutonPlanning}"
    Grid.Row="1" Grid.Column="2" Foreground="Red" FontWeight="Bold" />
    <Button x:Name="MeAM" Width="80" Height="70" Style="{StaticResource styleBoutonPlanning}"
    Grid.Row="2" Grid.Column="2" Foreground="Red" FontWeight="Bold" />
     
    <Button x:Name="JeMAT" Width="80" Height="70" Style="{StaticResource styleBoutonPlanning}"
    Grid.Row="1" Grid.Column="3" Foreground="Red" FontWeight="Bold" />
    <Button x:Name="JeAM" Width="80" Height="70" Style="{StaticResource styleBoutonPlanning}"
    Grid.Row="2" Grid.Column="3" Foreground="Red" FontWeight="Bold" />
     
    <Button x:Name="VeMAT" Width="80" Height="70" Style="{StaticResource styleBoutonPlanning}"
    Grid.Row="1" Grid.Column="4" Foreground="Red" FontWeight="Bold" />
    <Button x:Name="VeAM" Width="80" Height="70" Style="{StaticResource styleBoutonPlanning}"
    Grid.Row="2" Grid.Column="4" Foreground="Red" FontWeight="Bold" />
     
    <Button x:Name="SaMAT" Width="80" Height="70" Style="{StaticResource styleBoutonPlanning}"
    Grid.Row="1" Grid.Column="5" Foreground="Red" FontWeight="Bold" />
    <Button x:Name="SaAM" Width="80" Height="70" Style="{StaticResource styleBoutonPlanning}"
    Grid.Row="2" Grid.Column="5" Foreground="Red" FontWeight="Bold" />
    En gros, on a un bouton par demi-journée.

    Pour alimenter ces boutons, je faisais 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
    18
    19
    20
    21
    22
    void client_GetPlanningCompleted(object sender, Client.ServiceReference.GetPlanningCompletedEventArgs e)
            {
                try
                {
                    UpdateTextPlanning(LuMAT, e.Result[0].DispoMatin);
                    UpdateTextPlanning(LuAM, e.Result[0].DispoApresMidi);
                    UpdateTextPlanning(MaMAT, e.Result[1].DispoMatin);
                    UpdateTextPlanning(MaAM, e.Result[1].DispoApresMidi);
                    UpdateTextPlanning(MeMAT, e.Result[2].DispoMatin);
                    UpdateTextPlanning(MeAM, e.Result[2].DispoApresMidi);
                    UpdateTextPlanning(JeMAT, e.Result[3].DispoMatin);
                    UpdateTextPlanning(JeAM, e.Result[3].DispoApresMidi);
                    UpdateTextPlanning(VeMAT, e.Result[4].DispoMatin);
                    UpdateTextPlanning(VeAM, e.Result[4].DispoApresMidi);
                    UpdateTextPlanning(SaMAT, e.Result[5].DispoMatin);
                    UpdateTextPlanning(SaAM, e.Result[5].DispoApresMidi);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.InnerException.Message);
                }
            }
    La méthode UpdateTextPlanning se chargeant de rendre actif ou non le bouton et d'afficher "COMPLET" si non..

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    private void UpdateTextPlanning(Button boutonEnCours, Boolean dispo)
            {
                if (dispo)
                {
                    boutonEnCours.IsEnabled = true;
                    boutonEnCours.Content = "";
                }
                else
                {
                    boutonEnCours.IsEnabled = false;
                    boutonEnCours.Content = "COMPLET";
                }
            }
    A noter que la couleur change également, mais ça c'est géré directement dans le style (Vert si IsEnabled est à true, Gris si c'est à false).

    Ce test rapide m'a permis de voir que tout fonctionné parfaitement.

    J'ai donc entrepris d'améliorer un peu les choses :

    SOLUTION 1 : Dans cette première solution, j'ai ajouté un peu de binding.

    Ainsi, le code pour chaque de mes boutons devient :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    <Button x:Name="SaMAT" Width="80" Height="70" Style="{StaticResource styleBoutonPlanning}"
    IsEnabled="{Binding DispoMatin}" Grid.Row="1" Grid.Column="5" Foreground="Red" FontWeight="Bold" />
    Il me suffit ensuite faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SaMAT.DataContext = e.Result[5];
    Et c'est bon. Le bouton devient bien actif ou non selon la valeur de la propriété.

    Cependant, deux problèmes se posent :
    1 - Comment gérer l'apparition ou non du mot COMPLET quand DispoMatin (ou DispoApresMidi) est à false ?
    J'ai pensé à un Converter qui changerait le booleen en un string "COMPLET" ou vide, et ensuite j'ajoute un binding sur la propriété Content du bouton.

    Je pourrais également modifié mon service WCF pour envoyer directement cette info. Mais ça me plait pas trop comme solution.

    Ou je pourrais utiliser une solution à laquelle j'ai pas pensé

    J'aimerais faire les choses de la meilleure façon possible.

    2- L'autre problème vient du fait que je trouve ça rébarbatif de faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    leNomDuBoutton.DataContext = e.Result[5];
    pour chaque bouton. Ca en fait 12 (6 jours * 2 demi journée).

    Pour pallier à ce problème, j'ai donc envisagé la Solution 2.

    SOLUTION 2 : Utilisation du DataBinding et d'un ItemsControl.
    Pour cette solution, je me suis inspiré de cet excellent tuto (http://broux.developpez.com/articles...g-silverlight/).

    Le code XAML pour mon calendrier devient donc :

    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
    <ItemsControl x:Name="Calendrier" >
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <StackPanel Orientation="Horizontal" /> 
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <StackPanel Orientation="Vertical" >
                                    <Button x:Name="BtnDuMatin" Click="BtnDuMatin_Click" Width="80" Height="70" IsEnabled="{Binding DispoMatin}" />
                                    <Button x:Name="BtnApresMidi" Width="80" Height="70" IsEnabled="{Binding DispoApresMidi}" />
                                </StackPanel>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
    Côté code behind, j'ai juste à faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Calendrier.ItemsSource = e.Result;
    C'est sacrément plus court.

    Par contre, cette solution me soulève un nouveau problème (en plus de celui du mot COMPLET qui est commun aux deux solutions) :

    1- Dans la solution initiale (pour les tests de départ) et dans la solution 1, chaque bouton a un nom bien précis. C'était trés utile pour savoir sur quel bouton l'utilisateur a cliqué. Car c'est pas juste de l'affichage. En fait, je dois pouvoir savoir sur quelle demi-journée a cliqué l'utilisateur.

    Avec un nom de bouton différent pour chaque demi-journée, je faisais simplement :

    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
    private void CalendrierButton_Click(object sender, RoutedEventArgs e)
            {
                FrameworkElement fe = sender as FrameworkElement;
     
                switch (fe.Name)
                {
                    case "LuMAT":
                        // Je sais ou il a cliqué
                        break;
                    case "LuAM":
                        // Je sais ou il a cliqué
                        break;
                    case "MaMAT":
                        // Je sais ou il a cliqué
                        break;
                    // etc ....
                }
            }

    Pour cette solution 2, j'ai donné un nom à mes boutons : BtnDuMatin et BtnApresMidi. Mais comme l'ItemsControl agit comme un Repeater,
    tous mes boutons du matin portent le même nom. Ma question est donc simple, comment savoir sur quelle demi-journée a cliqué l'utilisateur ?

    Je sais que ça fait beaucoup de questions, mais j'aimerais vraiment faire les choses proprement. Merci de me donner vos conseils ou de m'indiquer une solution à laquelle je n'ai peut être pas pensé.

    Merci d'avance pour votre aide.
    Dernière modification par Deepin ; 14/01/2010 à 15h09. Motif: Balises [CODE]...[/CODE]

  2. #2
    Expert confirmé
    Avatar de Skyounet
    Homme Profil pro
    Software Engineer
    Inscrit en
    Mars 2005
    Messages
    6 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Software Engineer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 6 380
    Par défaut
    Alors je dis oui pour le Converter pour COMPLET, y'a franchement pas d'autres solution.

    Et pour le problème des boutons tu pourrais peut-être renvoyer avec ton WCF également le nom du jour et le binder sur la propriété Tag du bouton.
    Dans la callback du bouton tu fais un switch sur Tag.ToString().

  3. #3
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Skyounet Voir le message
    Alors je dis oui pour le Converter pour COMPLET, y'a franchement pas d'autres solution.

    Et pour le problème des boutons tu pourrais peut-être renvoyer avec ton WCF également le nom du jour et le binder sur la propriété Tag du bouton.
    Dans la callback du bouton tu fais un switch sur Tag.ToString().
    Ca me rassure, je pensais être passé à côté d'une solution.

    J'ai pas encore mis en place le Converter, mais j'ai testé ton idée avec le Tag. Par contre, j'ai pas modifié le service WCF. Il me renvoit déjà la Date, ça me suffit.

    J'ai donc modifié le bouton du matin et le bouton de l'aprés midi en ajoutant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Tag="{Binding PlanningDate}"
    Et j'ai testé en faisant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Button btn = sender as Button;
    MessageBox.Show(btn.Tag.ToString());
    Et .... ça marche !

    J'ai donc le Date et la demi-journée (grâce au nom du bouton). Je connais donc la demi-journée avec précision. C'est parfait ! Merci encore pour cette astuce.

  4. #4
    Invité
    Invité(e)
    Par défaut
    J'ai également mis en place le Converter grâce au même tuto (http://broux.developpez.com/articles...g-silverlight/) et tout fonctionne impec

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

Discussions similaires

  1. prob d'affichage d'un calendrier
    Par zaineb.z dans le forum Struts 1
    Réponses: 6
    Dernier message: 27/07/2007, 23h22
  2. prob d'affichage d'un calendrier
    Par zaineb.z dans le forum Servlets/JSP
    Réponses: 1
    Dernier message: 25/07/2007, 15h14
  3. Affichage d'un calendrier
    Par franckywood dans le forum Pascal
    Réponses: 3
    Dernier message: 06/07/2007, 19h45
  4. [debutant] Affichage d'un calendrier
    Par Ashgenesis dans le forum C
    Réponses: 16
    Dernier message: 01/03/2007, 18h29
  5. [Mozilla] Problème d'affichage d'un calendrier
    Par nais_ dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 07/09/2006, 10h50

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