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 :

[MVVM] Treeview complexe


Sujet :

Windows Presentation Foundation

  1. #1
    Membre à l'essai
    Inscrit en
    Mars 2012
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Mars 2012
    Messages : 19
    Points : 10
    Points
    10
    Par défaut [MVVM] Treeview complexe
    Bonjour,


    je débute en C#, en WPF et MVVM, soyez indulgent

    Je souhaite réaliser un Treeview qui me semble bien complexe.
    J'explique d'abord, je fais un dessin ensuite.

    Ce treeview devra être composé de Territoire qui possèdent eux même des Territoires, peu importe sur combien de niveau
    Chaque Territoire peut avoir 0-n Clients, 0-n Prospects, 0-n Employés.
    La représentation que je veux obtenir est celle ci :

    Nom : treeview.PNG
Affichages : 557
Taille : 13,1 Ko

    Sur fond bleu ce sont mes Territoires, imbriqués les uns dans les autres.
    600148 est fils de 311100 qui est lui même fils de 102101 etc.... jusqu'à la racine 300.

    Pour tous les autres éléments, Clients, Prospects et Employés, je souhaite mettre un nom d'entête et à coté y indiquer le nombre d’occurrence pour chaque. Je souhaite pouvoir customiser ces entêtes (images, couleur, font etc...)
    Ici le Territoire 600148 possède 302 Clients.
    Si je déroule Clients, je vois les 302.



    Comme vous pouvez le voir, je parviens à faire quelque chose lorsque je programme en vb.net façon winform...
    Je parviens aussi à faire une recherche dans ce treeview en le re-parcourant. Un seul textbox est utilisé pour chercher soit un Territoire, soit un Client, soit un Prospect etc...


    J'aimerai maintenant faire du WPF avec binding, ICommand pour la recherche et utiliser la méthode MVVM.
    J'ai tenté de suivre ce tuto de Josh Smith ainsi que la méthodologie de Jérémy Alles, mais j'ai du mal à comprendre le fonctionnement...
    Pour simplifier, je ne prends que les Territoires et les Clients, je créé bien 2 simples models :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    public class Territory
        {
            public string TerritoryID { get; set; }
        }
     
     
    public class Customer
        {
            public string CustomerID { get; set; }
        }

    Maintenant, je ne sais pas combien de ViewModel sont à créer, 1 pour chaqu'un de mes Models + 1 racine ?
    Comment représenter ma hiérarchie de Territoire, dans le Model en ajoutant une liste de Territoire ou dans le ViewModel?
    De même pour les Clients.

    Comment représenter le XAML pour afficher le répertoire 'Clients' et pouvoir par la suite le designer à ma guise dans la vue?

    Je suis perdu.


    Merci d'avance pour l'aide que vous pourrez m'apporter.
    @+

  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
    Déjà ton modèle devrait plus ressembler à une structure arborescente :

    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
    public class Territory
    {
        public string TerritoryID { get; set; }
     
        public IList<Territory> SubTerritories { get; set; }
     
        public IList<Customer> Customers { get; set; }
     
        public IList<Prospect> Prospects { get; set; }
     
        public IList<Employee> Employees { get; set; }
    }
     
     
    public class Customer
    {
        public string CustomerID { get; set; }
    }
    Puis tu dois utiliser des DataTemplates dont des HierarchicalDataTemplates pour les territoires.

    Etant donné que tu n'as qu'un seul type pour représenter tous les territoires (les intermédiaires et les finaux) alors il te faudra éventuellement en plus un DataTemplateSelector dont le rôle sera de choisir le template intermédiaire s'il n'y a pas de clients, prospects et employés ou le template final qui affiche la liste des clients, prospects et employés.
    Je ne pense pas que ce soit nécessaire, un seul template hiérarchique affichant ou pas les listes devrait le faire.

    Voilà dans les grandes lignes...
    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
    Membre à l'essai
    Inscrit en
    Mars 2012
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Mars 2012
    Messages : 19
    Points : 10
    Points
    10
    Par défaut
    Merci pour ta réponse Pragmateek.

    Je ne savais pas si c'est mon Model de base Territoire qui doit détenir les diverses listes (territoires, clients, prospect, employes) ou si c'était le ViewModel.


    J'ai fait quelque essai avec les HierarchicalDataTemplates.
    J'avoue ne pas savoir réellement quoi binder (le Model ou le ViewModel?) et comment.
    Par exemple pour les clients :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    <HierarchicalDataTemplate DataType="{x:Type ViewModel:CustomerViewModel}" ItemsSource="{Binding Customers}">
         <StackPanel Orientation="Horizontal">
              <Image Source="Images\Customer.png" Width="16" Height="16"/>
              <TextBlock>Clients</TextBlock>
          </StackPanel>
    </HierarchicalDataTemplate>
    ou

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    <HierarchicalDataTemplate DataType="{x:Type Model:Customer}" ItemsSource="{Binding Customers}">
         <StackPanel Orientation="Horizontal">
              <Image Source="Images\Customer.png" Width="16" Height="16"/>
              <TextBlock>Clients</TextBlock>
         </StackPanel>
    </HierarchicalDataTemplate>

    A quoi doit ressembler le ViewModel d'ailleurs. Est ce une simple surcouche qui expose les propriétés du Model?


    J'ai aussi testé un multibinding + converter pour afficher le nom des 'répertoires' :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    <MultiBinding Converter="{StaticResource monConverter}" ConverterParameter=", Clients, Prospects, Employés">
         <Binding Path="LstTerritory" />
         <Binding Path="LstCustomer" />
         <Binding Path="LstProspect" />
         <Binding Path="LstEmployee" />
    </MultiBinding>
    Mais je ne parviens pas à les customiser ensuite, ni à faire des recherches grâce à une ICommand.



    Je ne connaissais pas les DataTemplateSelector, je vais regarder cela.

  4. #4
    Membre à l'essai
    Inscrit en
    Mars 2012
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Mars 2012
    Messages : 19
    Points : 10
    Points
    10
    Par défaut
    Bonjour,


    Après plusieurs tentatives, voici ce que j'arrive à obtenir

    Nom : tv.PNG
Affichages : 433
Taille : 9,2 Ko

    (les nombres sont mes territoires, les noms débutant par C sont mes clients et par P mes prospects)



    Je parviens à hiérarchiser mes Territoires.
    Pour ces territoires, je parviens à afficher -ou non- les Clients et les Prospects.

    Par contre, je ne parviens pas à réaliser la même chose que sur la capture de mon 1er post, c'est à dire un entête de répertoire pour les Clients/Prospects (pour n'afficher qu'au choix : les Clients, les Prospects ou autres)
    Ici, ils s'affichent tous les uns sous les autres :

    Nom : tv2.PNG
Affichages : 563
Taille : 11,1 Ko


    Voici le XAML de ma fenêtre :
    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
     
    <Window x:Class="Treeview_Test_5.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:m="clr-namespace:Model"
            xmlns:local="clr-namespace:ViewModel"
            Title="MainWindow" Height="350" Width="525">
     
     
        <Grid>
            <TreeView ItemsSource="{Binding RootHierarchy}">
                <TreeView.Resources>
                    <HierarchicalDataTemplate DataType="{x:Type local:TerritoryViewModel}" ItemsSource="{Binding Children}">
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding IdTerritory}" />
                        </StackPanel>
                    </HierarchicalDataTemplate>
     
                    <HierarchicalDataTemplate DataType="{x:Type local:CustomerViewModel}" ItemsSource="{Binding Children}">
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding IdCustomer}" />
                        </StackPanel>
                    </HierarchicalDataTemplate>
     
                    <HierarchicalDataTemplate DataType="{x:Type local:ProspectViewModel}" ItemsSource="{Binding Children}">
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding IdProspect}" />
                        </StackPanel>
                    </HierarchicalDataTemplate>
                </TreeView.Resources>
            </TreeView>
        </Grid>
    </Window>

    Mes models

    TERRITORY :
    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
     
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    using System.Text;
     
    namespace Model
    {
        class Territory
        {
            private ObservableCollection<Territory> _lstTerritory = new ObservableCollection<Territory>();
            private ObservableCollection<Customer> _lstCustomer = new ObservableCollection<Customer>();
            private ObservableCollection<Prospect> _lstProspect = new ObservableCollection<Prospect>();
     
     
            public string IdTerritory { get; set; }
     
     
            public ObservableCollection<Territory> LstTerritory
            {
                get { return _lstTerritory; }
                set
                {
                    if (value == _lstTerritory) return;
     
                    _lstTerritory = value;
                }
            }
     
     
     
            public ObservableCollection<Customer> LstCustomer
            {
                get { return _lstCustomer; }
                set
                {
                    if (value == _lstCustomer) return;
     
                    _lstCustomer = value;
                }
            }
     
     
            public ObservableCollection<Prospect> LstProspect
            {
                get { return _lstProspect; }
                set
                {
                    if (value == _lstProspect) return;
     
                    _lstProspect = value;
                }
            }
        }
    }

    Prospect :
    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
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
     
    namespace Model
    {
        class Prospect
        {
            private string idProspect = string.Empty;
     
     
            public string IdProspect
            {
                get { return idProspect; }
                set
                {
                    if (value == idProspect) return;
     
                    idProspect = value;
                }
            }
        }
    }

    Client :
    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
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
     
    namespace Model
    {
        class Customer 
        {
            private string idCustomer = string.Empty;
     
     
            public string IdCustomer
            {
                get { return idCustomer; }
                set
                {
                    if (value == idCustomer) return;
     
                    idCustomer = value;
                }
            }
        }
    }

    Mes ViewModel


    Root:
    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
     
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    using System.Text;
    using Model;
     
     
    namespace ViewModel
    {
        class Root
        {
            readonly ReadOnlyCollection<TerritoryViewModel> _RootHierarchy;
     
     
            public Root(Territory[] territories)
            {
                _RootHierarchy = new ReadOnlyCollection<TerritoryViewModel>(
                    (from territory in territories
                     select new TerritoryViewModel(territory,null))
                     .ToList());
            }
     
     
            public ReadOnlyCollection<TerritoryViewModel> RootHierarchy
            {
                get { return _RootHierarchy; }
            }
        }
    }

    Territory :
    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
     
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    using System.Text;
    using Model;
     
     
    namespace ViewModel
    {
        class TerritoryViewModel : TreeviewItemViewModel
        {
            readonly Territory _territory;
     
     
            public TerritoryViewModel(Territory territory, TerritoryViewModel parent)
                : base(parent)
            {
                _territory = territory;
     
     
                foreach (Territory child in _territory.LstTerritory)
                {
                    base.Children.Add(new TerritoryViewModel(child, this));
                }
     
     
                foreach (Customer child in _territory.LstCustomer)
                {
                    base.Children.Add(new CustomerViewModel(child, this));
                }
     
     
                foreach (Prospect child in _territory.LstProspect)
                {
                    base.Children.Add(new ProspectViewModel(child, this));
                }
            }
     
     
            public string IdTerritory
            {
                get { return _territory.IdTerritory; }
            }
     
        }
    }

    Prospect :
    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
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Model;
     
    namespace ViewModel
    {
        class ProspectViewModel : TreeviewItemViewModel
        {
            Prospect _prospect;
     
            public ProspectViewModel(Prospect prospect, TerritoryViewModel parent)
                : base(parent)
            {
                _prospect = prospect;
            }
     
     
            public string IdProspect
            {
                get { return _prospect.IdProspect; }
            }
        }
    }


    Client :
    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
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Model;    
     
    namespace ViewModel
    {
        class CustomerViewModel : TreeviewItemViewModel
        {
            Customer _customer;
     
            public CustomerViewModel(Customer customer, TerritoryViewModel parent)
                : base (parent)
            {
                _customer = customer;
     
     
            }
     
     
            public string IdCustomer
            {
                get { return _customer.IdCustomer; }
            }
        }
    }

    Les TreeviewItem :
    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
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    using System.Text;
     
     
    namespace ViewModel
    {
        class TreeviewItemViewModel
        {
            readonly ObservableCollection<TreeviewItemViewModel> _children;
            readonly TreeviewItemViewModel _parent;
     
     
            protected TreeviewItemViewModel(TreeviewItemViewModel parent)
            {
                _parent = parent;
                _children = new ObservableCollection<TreeviewItemViewModel>();
            }
     
     
            public ObservableCollection<TreeviewItemViewModel> Children
            {
                get { return _children; }
            }
        }
    }


    Maintenant je ne parviens pas à 'finir', afin d'obtenir des répertoires.
    Je ne sais pas comment utiliser un Multibinding avec Converter ici, voir un DataTemplateSelector comme le propose Pragmateek...
    Une idée?


    à+.

Discussions similaires

  1. Treeview hierarchique complexe
    Par rad_hass dans le forum Windows Presentation Foundation
    Réponses: 3
    Dernier message: 07/01/2011, 16h17
  2. [WPF][C#] Problème de TreeView avec MVvM sans UserControl
    Par Manwë06 dans le forum Windows Presentation Foundation
    Réponses: 9
    Dernier message: 05/10/2010, 13h23
  3. [Treeview/MVVM] arbre non rafrachit suis à modif de collection
    Par Yogy dans le forum Windows Presentation Foundation
    Réponses: 4
    Dernier message: 26/09/2010, 00h50
  4. MVVM Treeview et SelectedNode ?!
    Par zax-tfh dans le forum Windows Presentation Foundation
    Réponses: 6
    Dernier message: 19/05/2009, 10h45

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