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] Template + héritage = problème


Sujet :

Windows Presentation Foundation

  1. #1
    Membre chevronné

    Homme Profil pro
    Appui fonctionnel senior
    Inscrit en
    Juin 2007
    Messages
    461
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Appui fonctionnel senior
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 461
    Points : 2 211
    Points
    2 211
    Par défaut [WPF] Template + héritage = problème
    Bonjour à tous,

    Je cherche actuellement à recréer une sorte d'explorateur de solution comme on peut le voir sur Visual Studio. J'essaye pour cela de respecter le pattern MVVM, même si je fais tout à la main, sans framework.

    Pour me simplifier la vie côté TreeView, j'ai créé une VM TreeViewItemViewModel (MVVM, c'est pas mal pour s'entraîner à la dactylographie ), qui me permet de gérer notamment la sélection de l'item et le lazy loading. Bref, du classique.

    Cependant, lorsque que je souhaite ensuite créer une autre VM qui dérive de cette première VM, mes templates WPF se "perdent" un peu : en effet, si je déclare un style pour le type dérivé, celui-ci est simplement ignoré. Je suis obligé de déclarer le style sur le type parent, ce qui casse bien entendu tout le système.

    Par exemple, avec le code suivant (PhysicalProjectFolderViewModel dérive de ProjectContainerViewModel):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    <HierarchicalDataTemplate DataType="{x:Type ViewModels:ProjectContainerViewModel}" ItemsSource="{Binding Children}">
        <StackPanel Orientation="Horizontal">
            <Image Source="..." Margin="2" />
            <TextBlock Text="{Binding Name}" />
        </StackPanel>
    </HierarchicalDataTemplate>
     
    <HierarchicalDataTemplate DataType="{x:Type ViewModels:PhysicalProjectFolderViewModel}" ItemsSource="{Binding Children}">
        <TextBlock Text="{Binding Name}" />
    </HierarchicalDataTemplate>
    Seul le template de ProjectContainerViewModel est pris en compte, même si je fournis bien un objet de type PhysicalProjectFolderViewModel.

    J'ai un peu parcouru le web pour trouver une solution, mais la seule que j'ai pu trouvé consiste à utilise un DataTemplateSelector. Dans la mesure où cette solution ne me paraît très "propre"...

    Est-ce donc que je m'y prends mal, ou existe-t-il une méthode recommandé pour signaler à WPF qu'il doit considérer l'héritage pour le templating ?

    Merci d'avance pour vos réponses

    EDIT : Je me suis trompé de catégorie en postant Merci au modérateur qui pourra déplacer mon sujet dans la section WPF.

  2. #2
    Membre expert
    Avatar de GuruuMeditation
    Homme Profil pro
    .Net Architect
    Inscrit en
    Octobre 2010
    Messages
    1 705
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : Belgique

    Informations professionnelles :
    Activité : .Net Architect
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2010
    Messages : 1 705
    Points : 3 568
    Points
    3 568
    Par défaut
    Bizarre, il devrait tenir compte de l'héritage.

    Exemple, en prenant tes templates comme base :

    Code xaml : 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
     
        <StackPanel>
            <StackPanel.Resources>
                <HierarchicalDataTemplate DataType="{x:Type WpfApplication1:ProjectContainerViewModel}"
                                          ItemsSource="{Binding Children}">
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="This is parent tempate "></TextBlock>
                        <TextBlock Text="{Binding Name}" />
                    </StackPanel>
                </HierarchicalDataTemplate>
     
                <HierarchicalDataTemplate DataType="{x:Type WpfApplication1:PhysicalProjectFolderViewModel}"
                                          ItemsSource="{Binding Children}">
                    <TextBlock Text="{Binding Name}" />
                </HierarchicalDataTemplate>
            </StackPanel.Resources>
            <TreeView>
                <TreeViewItem ItemsSource="{Binding TheList}"
                              Header="Test heritage" />
            </TreeView>
        </StackPanel>

    Les VMs:
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
        public class ProjectContainerViewModel
        {
            public List<ProjectContainerViewModel> Children { get; set; }
     
            public string Name { get; set; }
        }
     
        public class PhysicalProjectFolderViewModel : ProjectContainerViewModel
        {
     
        }

    Le code de la mainwindows :
    Code C# : 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 partial class MainWindow : Window
        {
            public List<ProjectContainerViewModel> TheList { get; set; }
     
            public MainWindow()
            {
                this.InitializeComponent();
     
                TheList = new List<ProjectContainerViewModel>();
     
                TheList.Add(new PhysicalProjectFolderViewModel { Name = "First", Children = new List<ProjectContainerViewModel> { new PhysicalProjectFolderViewModel { Name = "Second" }, new ProjectContainerViewModel { Name = "third" } } });
     
                DataContext = this;
     
     
            }
        }

    Tu devrais bien voir le "This is parent tempate" qu'avec le nom "third"
    Microsoft MVP : Windows Platform

    MCPD - Windows Phone Developer
    MCPD - Windows Developer 4

    http://www.guruumeditation.net

    “If debugging is the process of removing bugs, then programming must be the process of putting them in.”
    (Edsger W. Dijkstra)

  3. #3
    Membre chevronné

    Homme Profil pro
    Appui fonctionnel senior
    Inscrit en
    Juin 2007
    Messages
    461
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Appui fonctionnel senior
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 461
    Points : 2 211
    Points
    2 211
    Par défaut
    Pour le coup, j'aurai préféré me tromper quelque part plutôt que devoir faire face à un caprice de WPF...

    Je me demande si mon problème peut venir de l'implémentation du VM générique pour les TreeViewItem (inspirés en grosse partie à partir de cet article : http://www.codeproject.com/Articles/...g-the-ViewMode).

    Sinon je déclare toujours pour mes vues un contrôle personnalisé sur lequel je bind les VM. Or, pour économiser un peu, je ne fais jamais d'héritage depuis UserControl (dans lequel je place ensuite mes éléments), mais directement depuis le contrôle qui m'intéresse. Est-ce que ma façon de concevoir les vues peut casser certains fonctionnement de WPF ? J'essayerai ça plus en détails ce soir.

    En tout cas, merci pour ce premier retour : au moins, je sais maintenant qu'il y a un vrai problème dans mon code Je vais continuer d'expérimenter certaines choses et tenter de trouver une solution.

  4. #4
    Membre chevronné

    Homme Profil pro
    Appui fonctionnel senior
    Inscrit en
    Juin 2007
    Messages
    461
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Appui fonctionnel senior
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 461
    Points : 2 211
    Points
    2 211
    Par défaut
    Bon, j'ai partiellement solutionné mon problème !

    Le problème venait de ma méthode permettant de charger les différents noeuds-enfants d'un noeud :
    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
     
    protected override void LoadChildren()
    {
        foreach (IProjectItem pvm in _project.Items)
        {                
            if (pvm is IProjectContainer)
            {
                Children.Add(new ProjectContainerViewModel(( pvm as IProjectContainer ), this, IsLazyMode));
            }
            else
            {
                Children.Add(new ProjectItemViewModel(pvm, this, IsLazyMode));
            }
        }
    }
    En testant l'interface, je déduis s'il s'agit d'un "noeud-feuille" ou non, en créant le bon VM en fonction du cas. Du coup, en corrigant comme suis :
    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
     
    protected override void LoadChildren()
    {
        foreach (IProjectItem pvm in _project.Items)
        {  
            if (pvm is VirtualProjectFolder)
            {
                Children.Add(new VirtualProjectFolderViewModel((pvm as VirtualProjectFolder), this, IsLazyMode));
                continue;
            }
     
            if (pvm is IProjectContainer)
            {
                Children.Add(new ProjectContainerViewModel((pvm as IProjectContainer ), this, IsLazyMode));
                continue;
            }
            Children.Add(new ProjectItemViewModel(pvm, this, IsLazyMode));
        }        
    }
    le templating marche bien dans ce cas, ce qui, au final, est tout à fait normal

    Seul réel problème restant donc : comment éviter de faire ce genre de code bien crade dans mon VM

Discussions similaires

  1. Problème avec template + héritage
    Par vincepoencet dans le forum Langage
    Réponses: 10
    Dernier message: 21/09/2008, 22h09
  2. Template, héritage multiple et redéfinition
    Par Paul Atreide dans le forum Langage
    Réponses: 5
    Dernier message: 31/10/2006, 14h00
  3. template, héritage et std:deque
    Par jmtrivial dans le forum Langage
    Réponses: 7
    Dernier message: 27/09/2006, 15h08
  4. [héritage] Problème de cast
    Par mambo dans le forum Visual C++
    Réponses: 7
    Dernier message: 16/08/2006, 16h32
  5. [Héritage] problème intégrité référentielle
    Par Ouark dans le forum PostgreSQL
    Réponses: 2
    Dernier message: 24/01/2006, 18h47

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