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] Gestion du parent logique d'un item dans un ItemsControl


Sujet :

Windows Presentation Foundation

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 7
    Points : 3
    Points
    3
    Par défaut [WPF] Gestion du parent logique d'un item dans un ItemsControl
    Bonjour,

    j'aurais une petite interrogation concernant l'arbre logique en WPF.

    Voila mon soucis : j'ai un ItemsControl qui contient comme items des FrameworkElements. Cet ItemsControl contient aussi un TabControl, et je voudrais ajouter certains des items de l'ItemsControl dans le TabControl, sans les retirer de l'ItemsControl d'origine et sans avoir à passer par du binding. Quelque chose du genre :

    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    monItemsControl.monTabControl.Items.Add(monItemsControl.Items[0]);

    Evidement, si je fais ça, j'obtiens une exception comme quoi un objet ne peut pas avoir deux parents logiques et que je dois d'abord lui retirer son parent logique avant de l'ajouter ailleurs. J'ai donc utilisé RemoveLogicalChildren avant de l'ajouter. Mais ça ne m'arrange pas que le parent logique de mon item soit monItemsControl.monTabControl plutôt que monItemsControl ... et RemoveLogicalChildren étant protected, je n'ai pas accès à monItemsControl.monTabControl.RemoveLogicalChildren !

    Ma question est donc la suivante : Y a-t-il un moyen quelconque pour ajouter un item dans un TabControl (et donc par extension dans tout ItemsControl) sans que cela impacte sur son parent logique ? Et si non quelqu'un aurait-il une idee quelconque sur comment rétablir le parent logique d'origine ?

    Merci d'avance ^^

  2. #2
    Rédacteur
    Avatar de Thomas Lebrun
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    9 161
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 9 161
    Points : 19 434
    Points
    19 434
    Par défaut
    Je ne suis pas sur d'avoir compris Tu peux réexpliquer ?

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 7
    Points : 3
    Points
    3
    Par défaut
    Pour simplifier, l'idée est la suivante :

    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    // On crée un FrameworkElement quelconque
    Button monBouton = new Button();
     
    // On l'ajoute à un premier ItemsControl : itemsControl1
    itemsControl1.Items.Add(monBouton);
     
    // On ajoute le même à un deuxième ItemsControl : itemsControl2
    itemsControl2.Items.Add(monBouton);

    Cela provoque une exception : "Element already has a logical parent. It must be detached from the old parent before it is attached to a new one."

    Il y a bien une méthode RemoveLogicalChild provenant de FrameworkElement, mais qui est protected et donc utilisable seulement si on est à l'intérieur du composant.

    La question est donc : puis-je ajouter le FrameworkElement (monBouton) au deuxième ItemsControl (itemsControl2) sans avoir à changer son Parent logique ? (Et sans passer par du binding sur les ItemsCollection)

  4. #4
    Rédacteur
    Avatar de Thomas Lebrun
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    9 161
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 9 161
    Points : 19 434
    Points
    19 434
    Par défaut
    Tu as la réponse dans le message de l'exception:

    Element already has a logical parent. It must be detached from the old parent before it is attached to a new one.
    Tu ne peux donc pas le faire à moins de le détaher de son parent (itemsControl1).

    On peut savoir ce que tu cherches à faire ?

  5. #5
    Membre à l'essai
    Inscrit en
    Mai 2007
    Messages
    32
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 32
    Points : 22
    Points
    22
    Par défaut
    Ah oui, bonne question par la même occasion :

    on fait comment pour détacher un contrôle de son parent ???

    J'aimerais bien savoir comment faire ça pour pouvoir déplacer un contrôle via drag and drop, par exemple le passage d'un objet d'une ListBox dans un WrapPanel...

  6. #6
    Candidat au Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 7
    Points : 3
    Points
    3
    Par défaut
    Bon en fin de compte vu que ça ne m'arrangeait vraiment pas de devoir changer le parent logique, j'ai fini par passer par du binding.

    Citation Envoyé par BruceWayne Voir le message
    Ah oui, bonne question par la même occasion :

    on fait comment pour détacher un contrôle de son parent ???

    J'aimerais bien savoir comment faire ça pour pouvoir déplacer un contrôle via drag and drop, par exemple le passage d'un objet d'une ListBox dans un WrapPanel...
    Il y a une méthode RemoveLogicalChild qui provient de FrameworkElement (ou FrameworkContentElement), mais cette méthode est protégée, tu ne peux dont l'appeler que si tu es à l'intérieur de ton composant ou d'un de ses dérivés. Du coup tu ne dois pas pouvoir l'utiliser si tu n'as que des composants d'origines (type ListBox et WrapPanel). Par contre j'imagine que rien ne t'empêche de retirer complètement le contrôle du premier composant pour l'ajouter au deuxième (genre ListBox.Remove puis WrapPanel.Children.Add).

  7. #7
    Candidat au Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mai 2008
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 2
    Points : 3
    Points
    3
    Par défaut Suppression d'un enfant dans un logicalview
    Je suis en WPF fk 4.6 vs2017

    J'ai un objet UIElement qui est dans une border.

    Je récupère cette border r avec une méthode ToDecorator() que j'ai faite. Si vous avez directement l'objet par son nom, c'est pareil.

    Decorator r = resourceName.ToDecorator();

    Je mémorise son enfant.
    UIElement r2 = r.Child;

    Je supprime les enfants de ma bordure
    r.Child = null;

    r2 est maintenant un UIElement qui n'a pas de parent et je peux l'insérer autre part sans problème.

    Hope this will help

  8. #8
    Membre régulier Avatar de _champy_
    Homme Profil pro
    Chef de projet progiciel patrimoine route/tram/aeroport
    Inscrit en
    Novembre 2017
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projet progiciel patrimoine route/tram/aeroport
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2017
    Messages : 26
    Points : 75
    Points
    75
    Par défaut
    Visiblement tu cherche à ajouter un même bouton à deux ItemsControl différents.
    Ce n'est pas possible !!! En WPF un contrôle à un seul parent.

    En revanche tu peut ajouter deux boutons différents à deux ItemsControl différents.

    Tu créer une classe ButtonFactory (static ou singleton) capable d'instancier un bouton avec des caractéristiques précises (la commande qu'il déclenche, le texte qu'il contient, son icône, largeur, hauteur) pour éviter une redondance de code.
    Par exemple une méthode CreateButton(ICommand command,string text,string iconPath, int32 width,int32 height)

    Tu peut même simplifier l'appel en créant la même méthode avec une signature différente dans ButtonFactory avec un seul paramètre au hasard une enum

    CreateButton(ButtonTypeEnum buttonType), cette méthode appel la précédente avec les bons paramètres (la commande qu'il déclenche, le texte qu'il contient, son icône, largeur, hauteur).

    Et enfin tu fait 2 instance de Button grâce à ta ButtonFactory :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Button monBouton1 = ButtonFactory.CreateButton(ButtonTypeEnum.ValidateButton);
    itemsControl1.Items.Add(monBouton1);
     
    Button monBouton2 = ButtonFactory.CreateButton(ButtonTypeEnum.ValidateButton);
    itemsControl2.Items.Add(monBouton2);

  9. #9
    Expert confirmé
    Inscrit en
    Avril 2008
    Messages
    2 564
    Détails du profil
    Informations personnelles :
    Âge : 64

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 564
    Points : 4 441
    Points
    4 441
    Par défaut
    bonjour

    Sujet absconse certes ,mais il existe 2 voies :
    1/Si l' Elément FrameworkElement que tu cherches à dupliquer(cloner) est crée :
    - via un Modèle (un DataTemplate ou un ContentTemplate alors il suffit de créer un Control du même -virginal- du même Type et de lui associer simultanément la prop CLR Data blindée et l'un des 2 Modèles possibles cités associes à ton Elément FrameworkElement ci-avant par code ..
    La puissance du modèle de données WPF se chargera de le reproduire intégralement ...
    MSDN Help Library citation :

    2/ Si l' Elément FrameworkElement que tu cherches à dupliquer(cloner) est crée :
    -manuellement via designer ou rajouter par code ,olà ,il est possible de le "photographier" par code grâce aux 2 class XamlWriter & XamlReader (les 2 Stooges de WPF,en fait ils étaient 3 comiques américains)...

    exemple code :
    code XAML du Form:
    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
     
    <Window x:Class="WpfDragDrop.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
     
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <Grid  Grid.Column="0">
                <Button Name="btn1" Background="Yellow"  Foreground="Red"  Click="btn1_Click"  Content="Button1" ></Button>
            </Grid>
            <Grid  Grid.Column="1">
                <StackPanel Name="panelstack" Background="Beige" />
            </Grid>
            <Grid  Grid.Column="2">
                <WrapPanel Name="panelwrap" Background="AliceBlue" ></WrapPanel>
            </Grid>
        </Grid>
    </Window>
    et son code behind .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
    47
    48
    49
    50
    51
    52
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    //rajouter ces espaces de nom
    using System.Windows.Markup ;
    using System.IO;
    using System.Xml;
     
    namespace WpfDragDrop
    {
        /// <summary>
        /// Logique d'interaction pour MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
     
            private void btn1_Click(object sender, RoutedEventArgs e)
            {
                Button btn = (Button)Clone(btn1);
                this.panelstack.Children.Add(btn);
                btn = (Button)Clone(btn1);
                this.panelwrap.Children.Add(btn);
            }
            public Control Clone(Control ctl)
            {
                //Clone the grid control
                var o = XamlWriter.Save(ctl);
                var sr = new StringReader(o);
                var reader = XmlReader.Create(sr, new XmlReaderSettings());
     
                var result = (Control)XamlReader.Load(reader);
                return result;
            }
     
     
        }
    }
    bon code...

  10. #10
    Membre chevronné
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    897
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 897
    Points : 1 913
    Points
    1 913
    Par défaut
    Opération "Herbert West", déterrage d'un post de 2008, j'espère que l'auteur originel a résolu son problème depuis le temps

  11. #11
    Membre régulier Avatar de _champy_
    Homme Profil pro
    Chef de projet progiciel patrimoine route/tram/aeroport
    Inscrit en
    Novembre 2017
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projet progiciel patrimoine route/tram/aeroport
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2017
    Messages : 26
    Points : 75
    Points
    75
    Par défaut
    Bon en même temps c'est à la mode les morts vivants

Discussions similaires

  1. [Débutant] [VB.NET/WPF] - Gestion de dossiers favoris
    Par shurikeNzL dans le forum VB.NET
    Réponses: 0
    Dernier message: 04/06/2012, 09h08
  2. [XL-2007] Gestion des Item dans un TCD en VBA
    Par BAHIRI dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 05/03/2012, 01h51
  3. [wpf] Gestion des Events : selection d'un item d'une treeview
    Par Flaburgan dans le forum Windows Presentation Foundation
    Réponses: 8
    Dernier message: 06/01/2011, 16h23
  4. desselectionner item dans treeview wpf
    Par aurel_le_ouf dans le forum Windows Presentation Foundation
    Réponses: 1
    Dernier message: 27/10/2010, 11h27
  5. Gestion des exceptions : logique qui m'étonne
    Par zax-tfh dans le forum VB.NET
    Réponses: 10
    Dernier message: 06/04/2007, 14h06

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