locked
Créer des items du controle pivot dynamiquement RRS feed

  • Question

  • Bonjour a tous,

    J'ai créer une page pivot pour mon appli WP7 en relation avec un WebService WCF.

    Dans cette page je souhaiterai afficher des "Questions" stocker en bd.

    Chaque question serai contenu dans un item du contrôle : ( a chaque glisser du doigt de droite a gauche l'utilisateur passerai a la question suivante ) avec bien entendu un choix de réponse possible en relation avec la bonne question.

    J'ai tenter plusieurs chose, mais a chaque fois le résultat affiche ma dernière question en bd et ses réponse sur un seul item :

    void myservice_ListerQuestionCompleted(object sender, QuizWS.ListerQuestionCompletedEventArgs e)
            {
                int i = 1;
                foreach (var question in e.Result)
                {
                    PivotQuestion.Items.Add("Question " + i);
                    i++;
                    textBlocQuestion.Text = question.nom;
                    buttonRep.Content = question.reponse;
                    buttonRep2.Content = question.reponse2;
                    buttonRep3.Content = question.reponse3;
                }
               
            }

    Merci par avance pour votre aide.

    lundi 25 juin 2012 07:07

Réponses

  • A ta place je ferais une nouvelle classe façon ViewModel pour gérer les données.

    Dans la nouvelle classe :

    public class MainPageViewModel
        {
            private MonServiceClient client;
            public ObservableCollection<Question> MesQuestions { get; set; }

            public MainPageViewModel()
            {
                client = new MonServiceClient();
                client.ListerQuestionAsync();
                client.ListerQuestionCompleted += new blablabla
            }


            void myservice_ListerQuestionCompleted(object sender, ListerQuestionCompletedEventArgs e)
            {
                if (e.Result == null)
                    return;
                else
                {
                    MesQuestions = null;
                    MesQuestions = e.Result;
                }
            }
        }

    Dans le code behind de ta page :

    public MainPage()
    {
               InitializeComponent();
               this.DataContext = new MainPageViewModel();
    }

    Et pour la vue :

    <Grid x:Name="LayoutRoot" Background="Transparent">
            <controls:Pivot Title="Questions" ItemsSource="{Binding MesQuestions}">
                <controls:Pivot.HeaderTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding nom}" />
                    </DataTemplate>
                </controls:Pivot.HeaderTemplate>
                <controls:Pivot.ItemTemplate>
                    <DataTemplate>  
                        <StackPanel>
                            <Button Content="reponse" />
                            <Button Content="reponse2" />
                            <Button Content="reponse3" />
                        </StackPanel>
                    </DataTemplate>
                </controls:Pivot.ItemTemplate>
            </controls:Pivot>
    </Grid>


    D'ailleurs, j'aurais probablement créé un objet Reponse, pour faire un sorte que l'objet Question contienne une collection de Reponse.
    Je trouve ça plus aisé mais ce n'est que mon avis ^^

    PS : désolé, l'insertion de code me donnait un formatage étrange :)


    Blog => http://ashworks.fr | Site => http://alexismathieu.com[/url] | Twitter => http://twitter.com/ashura95


    mardi 26 juin 2012 15:02

Toutes les réponses

  • Bonjour,

    C'est tout à fait possible. Le hic, c'est que tu vas devoir créer tout tes éléments à la main.
    Exemple:

    for(var i = 0; i < 10; i++)
    {
        var pi = new PivotItem { Header = "Title" + i };
        var gd = new Grid();
        var tb = new TextBlock() { Text = "test" };
    
        gd.Children.Add(tb);
        pi.Content = gd;
        PivotDyn.Items.Add(pi);
    }

    Cordialement,

    Mafyou.

    lundi 25 juin 2012 08:22
  • Merci beaucoup Mafyou, ça marche parfaitement.

    Mais comme je créer les contrôle directement en code, comment les designer via blend ?

    Quand j'ouvre mon projet dans blend je n'es pas accès a ces contrôle.

    Par avance merci.

    lundi 25 juin 2012 10:01
  • Hmm... Je m'en doutais que tu allés demande ça ^^

    Enfaite, c'est que tu fais une fois statiquement: tu déclares tes contrôles en XAML.
    Une fois cela fait, tu les écris en c# avec les même propriété qu'en XAML.

    lundi 25 juin 2012 10:12
  • Merci Mafyou pour vos réponse et votre aide. Grâce a vous je sent que j'avance.

    J'ai donc créer dans le xaml les contrôles que j'avais déclarer dans ma boucle c# avec le même "x:name"

    Code c# :

     foreach (var question in e.Result)
                {
                    var pivotItem = new PivotItem { Header = "Question " + i };
                    i++;
                    var GridItem = new Grid();
                    var textBlockQuestion = new TextBlock() { Text = question.nom };
                    var buttonRep1 = new Button() { Content = question.reponse };
                    var buttonRep2 = new Button() { Content = question.reponse2 };
                    var buttonRep3 = new Button() { Content = question.reponse3 };
                    var stackPanelReponse = new StackPanel();
    
                    GridItem.Children.Add(stackPanelReponse);
                    stackPanelReponse.Children.Add(textBlockQuestion);
                    stackPanelReponse.Children.Add(buttonRep1);
                    stackPanelReponse.Children.Add(buttonRep2);
                    stackPanelReponse.Children.Add(buttonRep3);
                    pivotItem.Content = GridItem;
                    PivotQuestion.Items.Add(pivotItem);
            }

    Le code xaml :

    <!--Contrôle Pivot-->
            <controls:Pivot x:Name="PivotQuestion" Title="1001 Test" FontFamily="/1001Test;component/Fonts/Fonts.zip#Century Gothic" FontSize="21.333">
                <controls:PivotItem x:Name="pivotItem">
                    <Grid x:Name="GridItem" >
                        <StackPanel x:Name="stackPanelReponse">
                        <TextBlock x:Name="textBlockQuestion" />
                        <Button x:Name="buttonRep1" />
                        <Button x:Name="buttonRep2" />
                        <Button x:Name="buttonRep3" />
                        </StackPanel>
                    </Grid>
                </controls:PivotItem>
            </controls:Pivot>

    Lorsque je design ces contrôle dans blend, seul les contrôles "statique" applique le design. De plus dans mon pivot cela me créer une nouvelle pages avec les contrôles vide.

    Par avance merci pour aide.

    lundi 25 juin 2012 11:40
  • Ton code XAML doit juste ressembler à celà:

    <controls:Pivot x:Name="PivotQuestion" Title="1001 Test" FontFamily="/1001Test;component/Fonts/Fonts.zip#Century Gothic" FontSize="21.333" />

    Ensuite, c'est le code C# qui va générer le reste.

    Pour ce qui est de ce code d'ailleur, il faut d'abord setter les éléments avande les ajouter aux conteneur.
    C'est à dire:

     foreach (var question in e.Result)
                {
                    var pivotItem = new PivotItem { Header = "Question " + i };
                    var textBlockQuestion = new TextBlock() { Text = question.nom };
                    var buttonRep1 = new Button() { Content = question.reponse };
                    var buttonRep2 = new Button() { Content = question.reponse2 };
                    var buttonRep3 = new Button() { Content = question.reponse3 };
                    var stackPanelReponse = new StackPanel();
                    stackPanelReponse.Children.Add(textBlockQuestion);
                    stackPanelReponse.Children.Add(buttonRep1);
                    stackPanelReponse.Children.Add(buttonRep2);
                    stackPanelReponse.Children.Add(buttonRep3);
    
                    var GridItem = new Grid();
                    GridItem.Children.Add(stackPanelReponse);
                    pivotItem.Content = GridItem;
                    PivotQuestion.Items.Add(pivotItem);
                    i++;
            }


    lundi 25 juin 2012 12:05
  • Le soucis quand j’enlève le code xaml et laisse que la ligne que vous avez indiquer dans blend je n'es plus accès aux contrôles.

    Voici l'arbre visuel que j'ai dans blend :

    Je n'est accès qu'au pivotQuestion.

    désolé si mes question peuvent paraitre débile mais je débute.

    Merci pour votre aide.

    lundi 25 juin 2012 12:39
  • C'est normal, et c'est le but!
    Tous les contrôles vont être générés par le C#. Exécutez votre programme, et vous verrez le rendu.

    Ce n'est pas possible de les voir dans blend car ils sont créer dynamiquement. Pourquoi on ne peut pas les voir plus précisement? Car au moment de rendre votre page pivot en mode design (juste l'ouvrir dans blend), il ne va exécuter votre service.

    lundi 25 juin 2012 12:53
  • D'accord merci de votre réponse.

    Comment faite vous pour designer correctement vos contrôles créer par code ?

    lundi 25 juin 2012 13:04
  • Hmm... Je m'en doutais que tu allés demande ça ^^

    Enfaite, c'est que tu fais une fois statiquement: tu déclares tes contrôles en XAML.
    Une fois cela fait, tu les écris en c# avec les même propriété qu'en XAML.

    Et bien sûr tu retires tes contrôles du XAML!

    EDIT: Sinon, il y a la solution en MvvM du "Pivot.ItemTemplate" avec une liste bindée à l'itemSource du Pivot. C'est une meilleur pratique, c'est sûr ^^ mais vous devriez déjà progresser sur le MvvM pour cela :-)

    • Modifié Mafyou lundi 25 juin 2012 15:59 Autre concept
    • Proposé comme réponse Pascal Saille mardi 26 juin 2012 05:01
    lundi 25 juin 2012 13:35
  • Bonjour,

    Est-ce que vous avez testé la solution proposée ? Merci de partager avec nous les résultats,afin que d'autres personnes avec le même problème puissent profiter de cette solution.


    Cordialement, Pascal.

    Développeur Wpf/SilverLight/WinPhone7

    mardi 26 juin 2012 05:02
  • Bonjour Pascal, j'ai essayé plusieurs chose.Mais je n'arrive pas a bindé mes données sur les contrôles xaml.

    Tous les exemples que je trouve sur internet, créer une classe avec leurs accesseur ( Get - Set ), instancié un nouvelle objet en dur du style : 

      public class Auteur
        {
            public string  nom { get; set; }
            public string prenom { get; set; }
        }
    
      Auteur auteur = new Auteur(){
                nom = "Hugo",
                prenom = "Victor"
            };

    et passe la propriété de la classe avec path :

    <TextBlock x:Name="textBlockQuestion" Text="{Binding Path=prenom}" />
    

    Le problème dans mon cas et que je passe par ma classe: service1.svc.cs qui implémente mon interface contenu dans mon web service WPF.

    J’utilise ensuite mes fonctions contenu dans cette classe avec les événements completed et async.

    Donc je ne voie pas comment binding les propriété qui m’intéresse.

    Merci pour votre aide.



    mardi 26 juin 2012 07:23
  • <TextBlock x:Name="textBlockQuestion" Text="{Binding Path=prenom}" />

    Allez y doucement:

    • Comment la propriété "prenom" va être récupérer? Il faut mettre en place un DataContext sur votre page.
    • "prenom" respecte-t-elle les conventions de nommage? Non, c'est une propriété public, donc "Prenom". Et le mieux (c'est un choix ça) c'est en anglais.
    • Quel est le mode de binding? J'entends par là, qui va mettre à jour ces données? Toujours du ViewModel à la View? Donc "OneWay".
    • Lors du chargement de la page, est-ce que la propriété sera obtenu à la bonne valeur? Non, elle vient d'un service, c'est asynchrone. Donc on utilise la classe INotifyPropertyChanged (ou si vous utilisez un framework type MvvMLight, il faut que votre ViewModel hérite de ViewModelBase et lance la méthode RaisePropertyChanged au moment du set) afin de notifier à l'UI que la valeur est à rafraîchir.

    Cela peut avoir l'air compliquer, mais vous vous y habituerez rapidement :-)

    mardi 26 juin 2012 08:19
  • A ta place je ferais une nouvelle classe façon ViewModel pour gérer les données.

    Dans la nouvelle classe :

    public class MainPageViewModel
        {
            private MonServiceClient client;
            public ObservableCollection<Question> MesQuestions { get; set; }

            public MainPageViewModel()
            {
                client = new MonServiceClient();
                client.ListerQuestionAsync();
                client.ListerQuestionCompleted += new blablabla
            }


            void myservice_ListerQuestionCompleted(object sender, ListerQuestionCompletedEventArgs e)
            {
                if (e.Result == null)
                    return;
                else
                {
                    MesQuestions = null;
                    MesQuestions = e.Result;
                }
            }
        }

    Dans le code behind de ta page :

    public MainPage()
    {
               InitializeComponent();
               this.DataContext = new MainPageViewModel();
    }

    Et pour la vue :

    <Grid x:Name="LayoutRoot" Background="Transparent">
            <controls:Pivot Title="Questions" ItemsSource="{Binding MesQuestions}">
                <controls:Pivot.HeaderTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding nom}" />
                    </DataTemplate>
                </controls:Pivot.HeaderTemplate>
                <controls:Pivot.ItemTemplate>
                    <DataTemplate>  
                        <StackPanel>
                            <Button Content="reponse" />
                            <Button Content="reponse2" />
                            <Button Content="reponse3" />
                        </StackPanel>
                    </DataTemplate>
                </controls:Pivot.ItemTemplate>
            </controls:Pivot>
    </Grid>


    D'ailleurs, j'aurais probablement créé un objet Reponse, pour faire un sorte que l'objet Question contienne une collection de Reponse.
    Je trouve ça plus aisé mais ce n'est que mon avis ^^

    PS : désolé, l'insertion de code me donnait un formatage étrange :)


    Blog => http://ashworks.fr | Site => http://alexismathieu.com[/url] | Twitter => http://twitter.com/ashura95


    mardi 26 juin 2012 15:02
  • Désolé de cette réponse tardivement.

    Merci Alexis, j'ai donc refait mon projet, certes et heureusement j'en était au début.

    J'ai donc utiliser le pattern MVVM. Encore un peu de mal mais je me documente.

    Encore merci a tous pour vos conseils et votre aide.

    vendredi 29 juin 2012 19:06