+ Répondre à la discussion
Affichage des résultats 1 à 6 sur 6
  1. #1
    Membre régulier
    Inscrit en
    avril 2010
    Messages
    197
    Détails du profil
    Informations forums :
    Inscription : avril 2010
    Messages : 197
    Points : 82
    Points
    82

    Par défaut [C#] TreeView SelectedItem MVVM

    Bonjour (Bonsoir plutôt) à tous,

    Le titre est assez explicite, je n'arrive pas à récupérer l'élément sélectionné dans une TreeView que j'alimente dynamiquement suivant des requêtes vers une API Rest. J'utilise MVVM.
    Je me suis basé sur cet exemple : http://www.codeproject.com/KB/WPF/Tr...ViewModel.aspx

    Voici mon code :
    Xaml :
    Code xml :
    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 x:Class="DynamicTreeView.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:vm="clr-namespace:DynamicTreeView.ViewModel"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <TreeView ItemsSource="{Binding Folders}">
                <TreeView.ItemContainerStyle>
                    <!-- 
            This Style binds a TreeViewItem to a TreeViewItemViewModel. 
            -->
                    <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" />
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </TreeView.ItemContainerStyle>
     
                <TreeView.Resources>
                    <HierarchicalDataTemplate 
                      DataType="{x:Type vm:FolderViewModel}" 
                      ItemsSource="{Binding Children}"
                      >
                        <StackPanel Orientation="Horizontal">
                            <Image Width="16" Height="16" Margin="3,0" Source="Images\folder.png" />
                            <TextBlock Text="{Binding FolderName}" />
                        </StackPanel>
                    </HierarchicalDataTemplate>
                </TreeView.Resources>
            </TreeView>
        </Grid>
    </Window>

    code behind :
    Code c# :
    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
    using System.Windows;
    using DynamicTreeView.ViewModel;
    using System.Collections.Generic;
    using DynamicTreeView.Model;
    using System.Net;
    using System.Text;
    using System.Xml;
     
    namespace DynamicTreeView
    {
        /// <summary>
        /// Logique d'interaction pour MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
     
                List<Folder> list = new List<Folder>();
     
                WebClient serviceRequest = new WebClient();
                serviceRequest.Credentials = new NetworkCredential("username", "password");
                serviceRequest.Encoding = Encoding.UTF8;
     
                var res = serviceRequest.DownloadString("url");
     
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(res);
     
                XmlNode root = doc.DocumentElement;
                foreach (XmlElement elemUser in root.ChildNodes)
                {
                    list.Add(new Folder(elemUser.GetAttribute("title"), elemUser.GetAttribute("id")));
                }
     
                FolderViewModel viewModel = new FolderViewModel(list);
                base.DataContext = viewModel;
     
            }
        }
    }

    FolderViewModel :
    Code c# :
    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
    using DynamicTreeView.Model;
    using System.Collections.ObjectModel;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Text;
    using System.Xml;
     
    namespace DynamicTreeView.ViewModel
    {
        class FolderViewModel : TreeViewItemViewModel
        {
            readonly Folder _folder;
            readonly ReadOnlyCollection<FolderViewModel> _folders;
     
            public FolderViewModel(Folder folder)
                : base(null, true)
            {
                _folder = folder;
            }
     
            public FolderViewModel(List<Folder> folders)
            {
                _folders = new ReadOnlyCollection<FolderViewModel>(
                    (from folder in folders
                     select new FolderViewModel(folder))
                     .ToList());
            }
     
            public ReadOnlyCollection<FolderViewModel> Folders
            {
                get { return _folders; }
            }
     
            public string FolderName
            {
                get { return _folder.FolderName; }
            }
     
            public string FolderId
            {
                get { return _folder.FolderId; }
            }
     
            protected override void LoadChildren()
            {WebClient serviceRequest = new WebClient();
                serviceRequest.Credentials = new NetworkCredential("username", "password");
                serviceRequest.Encoding = Encoding.UTF8;
     
                var res = serviceRequest.DownloadString("url");
     
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(res);
     
                XmlNode root = doc.DocumentElement;
                List<Folder> list = new List<Folder>();
                foreach (XmlElement elemUser in root.ChildNodes)
                    list.Add(elemUser.GetAttribute("id")));
     
                foreach (Folder folder in list)
                    base.Children.Add(new FolderViewModel(folder));
            }
        }
    }

    qui hérite de TreeViewItemViewModel qui est le même que dans l'exemple.

    Merci d'avance.

  2. #2
    Modérateur

    Inscrit en
    décembre 2004
    Messages
    2 210
    Détails du profil
    Informations forums :
    Inscription : décembre 2004
    Messages : 2 210
    Points : 2 985
    Points
    2 985

    Par défaut

    Salut,

    Citation Envoyé par Air P-E
    Le titre est assez explicite, je n'arrive pas à récupérer l'élément sélectionné dans une TreeView
    Pour récupérer le SelectedItem au sein de ton ViewModel, il y a plusieurs possibilités :
    • Connaitre le TreeView dans ton ViewModel et utiliser la propriété SelectedItem du TreeView, mais ça casse le principe même du pattern MVVM
    • Faire une fonction de recherche récursive qui retourne le TreeViewItem dont la propriété IsSelected est True (un peu comme Josh Smith peux le faire dans son premier exemple "Family Tree with Text Search", cf ton lien), mais c'est dommage de devoir passer là et pas forcément performant.
    • Utiliser la propriété IsSelected d'un TreeViewItem pour affecter un TreeViewItem static : ça me semble pas casser le pattern et simple à mettre en place (tout est fait dans le set de la propriété IsSelected)

  3. #3
    Membre expérimenté Avatar de koyot3
    Inscrit en
    avril 2007
    Messages
    687
    Détails du profil
    Informations forums :
    Inscription : avril 2007
    Messages : 687
    Points : 573
    Points
    573

    Par défaut

    http://www.developpez.net/forums/d74...-selectednode/

    Un peu plus de détails ici

    bonne chance

  4. #4
    Membre confirmé
    Profil pro
    Étudiant
    Inscrit en
    avril 2009
    Messages
    247
    Détails du profil
    Informations personnelles :
    Âge : 26
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : avril 2009
    Messages : 247
    Points : 297
    Points
    297

    Par défaut

    Salut,
    tu peux passer par une ICollectionView et récupérer l'élément sélectionné grâce à l'évènement CurrentChanged.

  5. #5
    Membre expérimenté
    Homme Profil pro
    Développeur .NET
    Inscrit en
    juillet 2009
    Messages
    451
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : juillet 2009
    Messages : 451
    Points : 565
    Points
    565

    Par défaut

    Hello,

    Je sais pas si j'ai bien compris ton problème car j'ai pas regardé le code en détails, mais moi j'ai utilisé ce principe pour le même genre de problèmes et c'est pas trop mal (je trouve):
    http://www.codeproject.com/KB/silver...iggerDemo.aspx

    Cad un :
    - datatrigger pour dire que la valeur selectionnée a changé
    - un behavior qui va ensuite trouver le bon noeud à selectionner

    A+
    Christophe

  6. #6
    Membre régulier
    Inscrit en
    avril 2010
    Messages
    197
    Détails du profil
    Informations forums :
    Inscription : avril 2010
    Messages : 197
    Points : 82
    Points
    82

    Par défaut

    Bonjour à tous,

    Merci pour vos réponses.
    Désolé de répondre si tard, j'ai eu beaucoup de chose à faire entre-temps, j'ai aussi quasi-refait tout mon projet !
    Je suis parti à la base sur un projet entièrement en mvvm (en tout cas tenté ! ) mais vu la taille de mon projet, j'ai trouvé que ce pattern n'était pas du tout adapté et trop lourd à mettre en place... Du coup j'ai tout refait en code-behind (tout dégueu comme on aime mais tellement plus simple... ) sauf la partie treeview que j'ai laissé en mvvm car j'ai pas réussi autrement ! . Est-ce que celà va poser un problème pour la suite ? Sachant que je cherche toujours comment récupérer l'élément sélectionné.
    J'ai essayé de le récupérer avec "SelectedItemChanged" dans le code behind mais quand je l'affiche avec une MessageBox.Show(TreeView.SelectedItem.toString()); il m'affiche les objets de l'arbo.
    C'est à dire, à la première messageBox il m'affiche l'objet de l'élément sélectionné (je suppose), de suite après son parent, ainsi de suite... En gros je reviens toujours au root...

    @Binoo pour la solution de Josh Smith c'est exactement ce que je m'étais dit... c'est pourquoi je n'ai pas trop voulu m'y pencher... Cependant je suis intéressé par ta "méthode simple à mettre en place" mais je n'ai pas tout compris...

    @koyot3 : Merci mais c'est exactement le lien que j'ai mit dans mon premier post...

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •