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][C#] Problème de TreeView avec MVvM sans UserControl


Sujet :

Windows Presentation Foundation

  1. #1
    Futur Membre du Club
    Inscrit en
    Juin 2006
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 11
    Points : 6
    Points
    6
    Par défaut [WPF][C#] Problème de TreeView avec MVvM sans UserControl
    Bonjour à tous,

    C'est pas dans mon habitude de venir poser des questions, en général je finis toujours par trouver ce qui cloche dans mon code mais là je dois avouer qu'après 3 jours de recherches et de tutoriaux j'ai toujours pas tout compris de mon/mes erreur(s).

    Je débute en WPF, je suis pas un grand fan du XML sous toutes ses formes Mais ce truc permet tellement de customisation et un rendu UI tellement + attractif que WinForm que je suis convaincu de la rentabilité du temps investi pour créer mon appli


    Je vous explique mon soucis:
    J'ai suivi quelques tutoriaux sur le pattern MVvM, assez bien expliqués dans l'ensemble. Je commence à me familiariser avec les data binding (avant je m'en servais jamais XD) et je crois que c'est là que j'ai un soucis.
    Je veux créer une appli qui permet de virtualiser une arborescence "commune" à 3 disques durs différents. Le but est de créer une sorte de catalog de contenu qui ne soit pas dépendant de l'arborescence des disques, mais qui me permette de créer cette arborescence directement à partir de l'appli, en simultanée sur les 3 disques (et du coup d'uniformiser leur contenu si besoin, etc).

    J'en suis à la rédaction du code qui va lire le fichier XML (catalog). Le truc c'est que je ne pense pas avoir besoin d'un UserControl (View) pour mon TreeView, j'ai juste besoin de mes Models et ViewModels pour récupérer les infos que je veux afficher dans le TreeView que je customiserais grâce à un HierarchicalDataTemplate.

    Mon soucis c'est que je remplis bien mon ViewModel avec mes entrées XML, mais dans le treeview je vois que le type de mon viewmodel apparaitre (je sais que ça fait ça dans le cas d'absence de DataTemplate (en parsant par défaut le ToString() de ma classe)... mais moi j'en ai spécifié un !).

    Bref, très de bavardage, voici mon code, en espérant que vous puissiez éclairer ma lanterne qui s'est éteinte à l'entrée de ce tunnel bien noir ! :p

    -- Classe Data [DataClasses\RepositoryFolder.cs]
    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
     
        public class RepositoryFolder
        {
            string name;
            string repositoryPath;
            string svnPath;
            string wipPath;
            string finalPath;
            bool hasChilds;
            int assetCount;
     
            /* set / get */
     
            public RepositoryFolder(XmlNode _folderInfo)
            {
                name = _folderInfo.Attributes["name"].Value;
                repositoryPath = _folderInfo.NamespaceURI.ToString();
                svnPath = _folderInfo.Attributes["svnpath"].Value;
                wipPath = _folderInfo.Attributes["wippath"].Value;
                finalPath = _folderInfo.Attributes["finalpath"].Value;
     
                // Default values;
                hasChilds = _folderInfo.HasChildNodes;
                XmlNodeList assetChilds = _folderInfo.SelectNodes("FOOAsset");
                AssetCount = assetChilds.Count;
            }
        }
    Déjà est-ce correct que ma classe "data" soit si fortement typé sur le type d'ifnos en entrée ? (xmlnode) ou dois-je m'y prendre autrement ?

    -- ViewModels [ViewModelClasses\RepositoryViewItemViewModel.cs]
    C'est une version "améliorée" de ViewModelBase que j'ai trouvé sur le net ( ici si je me souviens bien).
    J'ai just modifié le type d'éléments des view items pour qu'ils concordent avec mes Viewmodels.

    -- ViewModels [ViewModelClasses\RepositoryViewModel.cs]
    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
     
        class RepositoryViewModel
        {
            private ObservableCollection<RepositoryFolderViewModel> repositoryStructure;
            private String repositoryXMLDocumentPath;
            public String XMLDocumentPath
            {
                get;
                set;
            }
     
     
            public RepositoryViewModel()
            {
                this.BuildListing();
            }
     
            public void BuildListing()
            {
                // Getting the first folders
                repositoryXMLDocumentPath = XMLDocumentPath != null ? XMLDocumentPath : @"I:\V13\Tools\FOOAssetsManager\FOOAssetsManager\FOOAssetsManager\TestRepository.xml";
                if (File.Exists(repositoryXMLDocumentPath))
                {
                    // loading the XML content
                    repositoryStructure = new ObservableCollection<RepositoryFolderViewModel>();
                    XmlDocument doc = new XmlDocument();
                    XmlTextReader reader = new XmlTextReader(repositoryXMLDocumentPath);
                    doc.Load(reader);
     
                    // Getting the first level of folders and creating the list to return
                    XmlNodeList firstLevelNodeList = doc.SelectNodes("Repository/Folder");
                    foreach (XmlNode node in firstLevelNodeList)
                    {
                        RepositoryFolder Folder = new RepositoryFolder(node);
                        RepositoryFolderViewModel FolderViewModel = new RepositoryFolderViewModel(Folder);
                        repositoryStructure.Add(FolderViewModel);
     
                    }
                }
            }
     
            public ObservableCollection<RepositoryFolderViewModel> RootFolders
            {
                get { return repositoryStructure; }
            }
        }
    La classe parente qui initialise les premiers nodes de mon treeview. Dans l'exemple donné dans le lien ci-dessus ça correspond à DriveViewModel (qui liste les sous-dossiers d'un disque dur)

    -- ViewModels [ViewModelClasses\RepositoryFolderViewModel.cs]
    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 class RepositoryFolderViewModel : RepositoryTreeViewItemViewModel
        {
            readonly RepositoryFolder currFolder;
     
            public RepositoryFolderViewModel(RepositoryFolder _folder, RepositoryFolderViewModel _parentFolder = null)
                : base(_parentFolder, true)
            {
                currFolder = _folder;
            }
     
            public String Name
            {
                get { return currFolder.Name; }
            }
     
            protected override void LoadChildren()
            {
                Console.WriteLine("Et là il faut charger les fils...");
            }
        }
    je ne me suis pas encore attelé à l'écriture de l'expand car pour l'instant j'aimerais déjà voir les premiers éléments s'afficher..., et que j'ai pas encore trop d'idée sur comment faire ça pour l'instant. Si vous avez une astuce pour récupérer le XPath d'un XmlNode dans le document je suis preneur !!

    Enfin, voici le code que j'ai mis dans ma MainWindow:
    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
     
    <Window
    ...
            xmlns:virtual="clr-namespace:AssetsManager.Controls.RepositoryTreeView"
    ...
     
    <Window.Resources>
            <virtual:RepositoryViewModel x:Key="Repository" XMLDocumentPath="TestRepository.xml"/>
        </Window.Resources>
    ...
    <TreeView DataContext="{Binding Source={StaticResource Repository}}" Loaded="TreeView_Loaded" ItemsSource="{Binding Path=RootFolders}">
                                    <TreeView.ItemContainerStyle>
                                        <Style TargetType="{x:Type TreeViewItem}">
                                            <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
                                            <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
                                            <Setter Property="FontWeight" Value="Normal" />
                                            <Style.Triggers>
                                                <Trigger Property="IsSelected" Value="True">
                                                    <Setter Property="FontWeight" Value="Bold" />
                                                    <Setter Property="Foreground" Value="Black" />
                                                </Trigger>
                                            </Style.Triggers>
                                        </Style>
                                    </TreeView.ItemContainerStyle>
                                    <TreeView.Resources>
                                        <HierarchicalDataTemplate x:Key="XMLFolders" 
                                                                  DataType="{x:Type virtual:RepositoryFolderViewModel}"
                                                                  ItemsSource="{Binding Path=Children}">
                                            <StackPanel Orientation="Horizontal">
                                                <CheckBox Width="16" Height="16" Margin="3,0"/>
                                                <Image Width="20" Height="20" Source="/AssetsManager;component/Images/Icons/folder.ico" />
                                                <TextBlock Text="{Binding Path=Name}" />
                                            </StackPanel>
                                        </HierarchicalDataTemplate>
                                    </TreeView.Resources>
                                </TreeView>
    ...
    Le Loaded="TreeView_Loaded" ne me sert à rien en fait. J'ai juste vu que dans la précédente adaptation que j'avais faite, il fallait que je bind le datacontext en code-behind après que le control soit loadé, mais c'était dans le cas d'un customControl...


    Voilà, j'espère qu'une (ou plusieurs) âme(s) charitable(s) pourra m'aider ! J'en ai un peu marre là de stagner depuis 3 jours

    PS : désolé si j'ai écrit un pavé, j'essaie d'être le plus précis possible.

  2. #2
    Membre expérimenté
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 562
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 562
    Points : 1 313
    Points
    1 313
    Par défaut
    fait un exemple dans un petit projet ca sera bcp plus simple pour corriger ton view model
    IKEAS : Finalement je crois que c'est dans ses faiblesses que l'on y trouve a la fois de la force et a la fois de la richesse...
    ----------------------------------------------------
    Si vous avez du taf en wpf & design d'application sympa, contactez moi !!!!
    http://ultimatecorp.eu/wpf/

  3. #3
    Futur Membre du Club
    Inscrit en
    Juin 2006
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 11
    Points : 6
    Points
    6
    Par défaut
    C'est déjà un petit projet, y'a rien d'autre à part ça C'est le début de mon projet en fait....

  4. #4
    Membre expérimenté
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 562
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 562
    Points : 1 313
    Points
    1 313
    Par défaut
    certe mais si tu met un zip de celui ci (c 'est ce que je voulais dire) ca sera plus simple lol
    IKEAS : Finalement je crois que c'est dans ses faiblesses que l'on y trouve a la fois de la force et a la fois de la richesse...
    ----------------------------------------------------
    Si vous avez du taf en wpf & design d'application sympa, contactez moi !!!!
    http://ultimatecorp.eu/wpf/

  5. #5
    Futur Membre du Club
    Inscrit en
    Juin 2006
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 11
    Points : 6
    Points
    6
    Par défaut
    Ah ok j'avais pas compris ça

    J'ai isole le treeview dans une nouvelle solution et je l'ai mise en pièce jointe.

    Merci beaucoup
    Fichiers attachés Fichiers attachés

  6. #6
    Membre expérimenté
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 562
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 562
    Points : 1 313
    Points
    1 313
    Par défaut
    deja on peut se demander pourquoi ta classe n'est pas une collection d'elle meme puisqu'au depart c'est une hierarchie d'element sur elle meme
    que tu mette un children dedans complique un peu

    a mon avis dans un premier temps tu devrais te faire une factory sur des elements simple que tu construit a la main

    avec le processus suivant
    1 - construction de la structure métier (la structure sur elle meme doit sensiblement être la même)
    2 - transformation de la structure métier en ViewModel

    de même il n'y a pas de différence entre un Folder et un item sinon que pour l'un on peut avoir des item sous jascent et que pour l'autre on en a pas (puisque qu'un item normal n'a pas de children) toutefois la classe peut etre la meme (ou avoir une derrivation de la meme classe de base pour avoir un type different)

    rectifi deja cela ....
    IKEAS : Finalement je crois que c'est dans ses faiblesses que l'on y trouve a la fois de la force et a la fois de la richesse...
    ----------------------------------------------------
    Si vous avez du taf en wpf & design d'application sympa, contactez moi !!!!
    http://ultimatecorp.eu/wpf/

  7. #7
    Futur Membre du Club
    Inscrit en
    Juin 2006
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 11
    Points : 6
    Points
    6
    Par défaut
    Citation Envoyé par ikeas Voir le message
    deja on peut se demander pourquoi ta classe n'est pas une collection d'elle meme puisqu'au depart c'est une hierarchie d'element sur elle meme
    que tu mette un children dedans complique un peu
    Moui, j'ai surtout repris l'exemple (qui marchait) d'un tuto bien fourni du net :p
    C'est aussi peut-être pour ça que je galère, mais il me fallait un point de départ avec les WPF ^^

    Citation Envoyé par ikeas Voir le message
    a mon avis dans un premier temps tu devrais te faire une factory sur des elements simple que tu construit a la main

    avec le processus suivant
    1 - construction de la structure métier (la structure sur elle meme doit sensiblement être la même)
    2 - transformation de la structure métier en ViewModel

    rectifi deja cela ....
    J'ai un peu de mal à comprendre XD.
    En fait mon RepositoryFolder est pas complet selon toi? Enfin à part le fait que pour l'instant il n'est pas récursif et ne construit donc pas d'arbre...
    Ce que je ne comprends pas vraiment c'est : si je fais mon arborescence dans ma classe RepositoryFolder... comment le ViewModel pourra afficher ça :s

    C'est fou en winform ça m'a pris 2h de comprendre le TreeView et de faire un parcours récursif des dossiers de mon disque dur, et là ça fait 3 jours que j'essaie de comprendre (c-a-d visualiser) comment écrire mon code pour que le TreeView l'affiche via data binding

  8. #8
    Membre expérimenté
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 562
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 562
    Points : 1 313
    Points
    1 313
    Par défaut
    une factory c'est une design pattern
    c'est generalement une classe static qui passe d'un format de quelque chose
    un fichier par exemple
    a autre chose
    une structure d'object
    par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    public static class TreeViewFactory
    {
    // pour creer un treeviewcollection a partir d'un fichier xml 
    // dont le chemin complet se trouve dans filename
     public static TreeViewCollection FromXmlFile(string filename)
     {
     }
    }
    pour l'utiliser on ferra
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    treeviewcollection tvc = TreeViewFactory.FromXmlFile(@"c:\toto.xml");
    IKEAS : Finalement je crois que c'est dans ses faiblesses que l'on y trouve a la fois de la force et a la fois de la richesse...
    ----------------------------------------------------
    Si vous avez du taf en wpf & design d'application sympa, contactez moi !!!!
    http://ultimatecorp.eu/wpf/

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Octobre 2007
    Messages : 15
    Points : 31
    Points
    31
    Par défaut
    Je n'ai pas bien compris le pourquoi du comment sur ta façon de faire.

    En tout cas si tu mets ça dans ton xaml t'auras déjà le premier niveau :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate
        DataType="{x:Type virtual:RepositoryFolderViewModel}"
        ItemsSource="{Binding Path=Children}">
            <StackPanel Orientation="Horizontal">
                <CheckBox Width="16" Height="16" Margin="3,0"/>
                <Image Width="20" Height="20" Source="/Images/Icons/folder.ico" />
                <TextBlock Text="{Binding Path=Name}" />
            </StackPanel>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>

  10. #10
    Futur Membre du Club
    Inscrit en
    Juin 2006
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 11
    Points : 6
    Points
    6
    Par défaut
    Grâce à Ikeas j'ai pu obtenir le premier niveau, mais comme il me l'a dit, je pense que j'suis parti dans du trop compliqué en prenant un code qui n'est pas de moi. Je vais essayer de tout reprendre à 0 avec quelque chose de + personnel, maintenant que je pense avoir un peu mieux saisi le MvvM.

    Je vais me pencher sur le DP de la Factory, ça semble vraiment sympa

    Dès que j'ai une soluce j'irais mettre une réponse plus approfondie sur ma nouvelle solution.

    @Alexlem: en fait dans mon post il y a un lien vers un tutorial à propos des treeview en WPF, et j'ai juste repris le code tout en faisant en sorte qu'il marche.... ou presque Du coup je pense que c'est top "évolué" pour pas grand chose !

Discussions similaires

  1. Réponses: 4
    Dernier message: 03/12/2014, 22h13
  2. Réponses: 4
    Dernier message: 28/03/2013, 12h26
  3. [C#/WPF] Visibility d'un élément avec MVVM
    Par Monkey56 dans le forum Windows Presentation Foundation
    Réponses: 7
    Dernier message: 30/08/2010, 20h28
  4. Réponses: 8
    Dernier message: 03/05/2007, 17h31
  5. Réponses: 7
    Dernier message: 23/07/2005, 12h50

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