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 :

Specified element is already the logical child of another element. Disconnect it first.


Sujet :

Windows Presentation Foundation

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    192
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 192
    Par défaut Specified element is already the logical child of another element. Disconnect it first.
    Bonjour,

    j'utilise des background worker pour éffectuer une recherche et ensuite afficher le résultat dans une datagrid. Chaque backgroundWorker appel la fonction AddJob ci dessous pour afficher de nouvelles infos dans ce datagrid.

    Lorsque je fais ma première recherche, ceci se passe bien.

    Lorsque je clique une seconde fois sur le bouton rechercher (recharge une nouvelle datagrid pour une nouvelle recherche), j'obtiens le message d’erreur suivant :

    Specified element is already the logical child of another element. Disconnect it first.
    Ceci apparait au niveau de l'utilisation du dispatcher (methode addJob).
    Je suppose que l'utilisation de RemoveLogicalChild ou RemoveVisualChild peut aider, mais je ne voit pas comment l'utiliser.

    Ci dessous le code. Merci pour votre aide !

    Code qui utilise un backgroud worker. Chaque background worker est censé créer une ligne dans ma datagrid via PageExecutionJob.JbList.AddJob
    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
     
    NavigationWindow popup = new NavigationWindow();
                    List<SCCMAdvertisement> lAdvFound = new List<SCCMAdvertisement>();
                    //Open the job summary window
                    popup.Show();
                    popup.Navigate(PageExecutionJob);
     
                    //List of BW that will containt the different BW created for the search of each site
                    List<BackgroundWorker> lBackJob = new List<BackgroundWorker>();
                    // Will start to search on selected promary Sites
                    foreach (SCCMSite site in lbSccmSites.SelectedItems)
                    {
                        //Create a thread for each site connection
                        lBackJob.Add(new BackgroundWorker());
     
                        //Get the latest BW from the list (1BW = 1SCCM Site to search)
                        BackgroundWorker bwLastGenerated = lBackJob.Last();
                        bwLastGenerated.WorkerSupportsCancellation = true;
     
                        //Define the job to be done for each BW
                        bwLastGenerated.DoWork += delegate(object s, DoWorkEventArgs args)
                        {
                            SCCMSite oBwSite = (SCCMSite)args.Argument;
                             //Display a new job in the Job List
                            PageExecutionJob.JbList.AddJob(oBwSite.Name, "Connection to WMI Database");
    lors de l'appel à PageExecutionJob.JbList.AddJob, ceci met à jour une une datagrid (via une observable collection)

    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
     
    /// <summary>
            /// Add a new Jod to the Datagrid
            /// </summary>
            /// <param name="target">Inform the user of the target of this job</param>
            /// <param name="description">Description of the process running</param>
            /// <returns></returns>
            public Job AddJob(string target, string description)
            {
                //Use the dispatcher  cause this function may be called from a thread, therefore it has to be executed in the Main UI thread
                //If no dispatcher = exception
     
    //ERREUR ICI QUAND JE RELANCE UNE SECONDE RECHERCHE
    Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
                    new Action(
                          delegate()
                          {
                              iJobInstanceID += 1;
                              _ocJobs.Add(new Job(iJobInstanceID, target, description));
                          }
                    ));
     
                return _ocJobs.Last();
            }
            }

  2. #2
    Membre Expert
    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
    Par défaut
    hello

    sans avoir creusé de trop ton code ce que je comprend pas c que tu veuille utiliser les visual ou logical
    en effet tu aurais une collection qui elle ferrait en sorte de se présenter par le biais du binding tu aurais pas ce genre de problème
    en effet
    ta grid (ou autre chose) est binder sur ta collection
    tu ajouter et tu supprime les elemenst de ta collection
    et forcement la représentation suivra ....

    c'est le principe de base de wpf, on s'interresse uniquement aux objets métiers
    voila

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    192
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 192
    Par défaut
    Salut Ikeas

    Merci pour ta réponse.
    Je pense effectivement bien binder ma datagrid via mon observable collection
    Je me permet de te mettre le code XAMl de mon control et le code behind.
    Je suis un peu débutant en WPF donc si jamais tu vois qqchose d'anormal....
    Merci pour ton aide

    XAML
    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
     
    <UserControl
                 x:Class="WPFControls.JobList"
    xmlns:wfi="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration" 
        xmlns:winForms="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                 mc:Ignorable="d" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" MinHeight="300" MinWidth="400" d:DesignHeight="284" d:DesignWidth="554">
     
        <Grid MinHeight="200" MinWidth="300" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
     
            <DataGrid x:Name="dgJob" AutoGenerateColumns="False" MinHeight="100" MinWidth="200"
                      RowHeight="25" AlternatingRowBackground="Gainsboro" Margin="0,0,0,40">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Target" Binding="{Binding Target}" Width="2*"/>
                    <DataGridTextColumn Header="Description" Binding="{Binding Description}" Width="6*"/>
                    <DataGridTemplateColumn  IsReadOnly="True" Width="2*">
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                <Image Source="{Binding ImagePath}" />
                                </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                        </DataGridTemplateColumn>
                </DataGrid.Columns>
            </DataGrid>
            <Button Content="Close" Name="btClose" IsEnabled="False" Click="btClose_Click" Margin="247,0,232,12" VerticalAlignment="Bottom" />
        </Grid>
    </UserControl>

    Code behind
    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
    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
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
     
    namespace WPFControls
    {
        /// <summary>
        /// Interaction logic for JobTreatment.xaml
        /// </summary>
        public partial class JobList : System.Windows.Controls.UserControl
        {
            private ObservableCollection<Job> _ocJobs = new ObservableCollection<Job>();
            PictureBox pictureBoxLoading;
            public ObservableCollection<Job> OcJobs
            {
                get { return _ocJobs; }
                set { _ocJobs = value; }
            }
            private int iJobInstanceID = 0;
     
            //Constructor
            public JobList()
            {
                InitializeComponent();
                dgJob.ItemsSource = _ocJobs;
            }
     
            /// <summary>
            /// Add a new Jod to the Datagrid
            /// </summary>
            /// <param name="target">Inform the user of the target of this job</param>
            /// <param name="description">Description of the process running</param>
            /// <returns></returns>
            public Job AddJob(string target, string description)
            {
                //Use the dispatcher  cause this function may be called from a thread, therefore it has to be executed in the Main UI thread
                //If no dispatcher = exception
     
                    Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
                    new Action(
                          delegate()
                          {
                              iJobInstanceID += 1;
                              _ocJobs.Add(new Job(iJobInstanceID, target, description));
                          }
                    ));
     
                return _ocJobs.Last();
     
            }
     
            /// <summary>
            /// Add a new job to the datagrid
            /// </summary>
            /// <param name="Target"></param>
            /// <param name="Description"></param>
            /// <param name="jobStatus"></param>
            public virtual void UpdateJob(string Target, string Description, Job.JobStatusValue jobStatus)
            {
                    this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
                    new Action(
                    delegate()
                    {
                        Job jobToUpdate = (Job)_ocJobs.First(job => job.Target == Target);
                        jobToUpdate.Description = Description;
                        jobToUpdate.Status = jobStatus;
     
                        _ocJobs.Remove(jobToUpdate);
                        _ocJobs.Add(jobToUpdate);
                        dgJob.Items.Refresh();
     
                        //Check if there is no more job running. If Yes, enable close button
                        int iJobNotDone = _ocJobs.Count(job => job.Status == Job.JobStatusValue.Running);
                        if (iJobNotDone == 0) btClose.IsEnabled = true;
                    }
                    ));
     
                //}
            }
     
            /// <summary>
            /// Button closed (enabled once all job are not anymore in Running status)
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btClose_Click(object sender, RoutedEventArgs e)
            {
                this.Content = null;
                _ocJobs = null;
                dgJob = null;
                Window parentwin = Window.GetWindow(this.Parent);
                //Dispatcher.InvokeShutdown();
                parentwin.Close();
            }
        }
     
        /// <summary>
        /// The datagrid contains Job Objects (binding via XAML)
        /// </summary>
        public partial class Job
        {
            // declares the dufferent job status values
            public enum JobStatusValue
            {
                NotStarted,
                Running,
                DoneSuccessfully,
                DoneWarning,
                DoneError,
            }
     
            int _ID;
            JobStatusValue _status;
            string _description;
            BitmapImage _sImagePath;
     
            public JobStatusValue Status
            {
                get { return _status; }
                set { _status = value; UpdateJobImage(); }
            }
     
            public int ID
            {
                get { return _ID; }
                set { _ID = value; }
            }
     
            string _target;
     
            public string Target
            {
                get { return _target; }
                set { _target = value; }
            }
     
     
            public string Description
            {
                get { return _description; }
                set { _description = value; }
            }
     
            public BitmapImage ImagePath
            {
                get { return _sImagePath; }
                set { _sImagePath = value; }
            }
     
            public Job(int IDJob, string target, string description)
            {
                _ID = IDJob;
                _status = JobStatusValue.Running;
                _target = target;
                _description = description;
                _sImagePath = null;
            }
     
            private void UpdateJobImage()
            {
     
                if (_status == JobStatusValue.DoneSuccessfully)
                {
                    Uri uri = new Uri("pack://application:,,,/WPFControls;component/Resources/Actions-dialog-ok-apply-icon.png");
                    BitmapImage img = new BitmapImage(uri);
                    _sImagePath = img;
                }
                else if (_status == JobStatusValue.DoneWarning)
                {
                    Uri uri = new Uri("pack://application:,,,/WPFControls;component/Resources/Actions-messagebox-warning-icon.png");
                    BitmapImage img = new BitmapImage(uri);
                    _sImagePath = img;
                }
                else if  (_status == JobStatusValue.DoneError)
                 {
                     Uri uri = new Uri("pack://application:,,,/WPFControls;component/Resources/Actions-window-error-icon.png");
                    BitmapImage img = new BitmapImage(uri);
                    _sImagePath = img;
                }
             }
     
        }
    }

  4. #4
    Membre Expert
    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
    Par défaut
    premier chose tu pourrais directement faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
     <DataGrid x:Name="dgJob" ItemsSource={Binding OcJobs}"...
    avec

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    public JobList()
    {
    InitializeComponent();
    this.DataContext = this;
    }
    et a part ca
    tu ne dois pas utiliser dgJob ni _ocJobs dans ton code
    si tes propriétés sont correctement faites tu n'en a pas besoin

    et ça par exemple c'est de nature a mettre la pagaille
    _ocJobs = null;
    dgJob = null;

    ne travail qu'avec OcJobs c'est une observablecollection c fait pour

    évidement ta class Job
    doit etre INotifyPropertyChanged
    et integrer le OnPropertyChanged dans chaque methode set
    ca va de soit

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    192
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 192
    Par défaut
    Salut Ikeas.

    J'ai apporté les changements comme indiqué et cela fonctionne

    Encore Merci.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. A control is already associated with the element
    Par oliver254 dans le forum ASP.NET
    Réponses: 6
    Dernier message: 26/01/2010, 19h24
  2. Réponses: 0
    Dernier message: 20/01/2010, 17h57
  3. comment récupérer un element dans un listbox via un template d'element
    Par Pol63 dans le forum Windows Presentation Foundation
    Réponses: 16
    Dernier message: 28/04/2009, 23h17
  4. facet already has a child associated
    Par *alexandre* dans le forum JSF
    Réponses: 1
    Dernier message: 22/09/2006, 15h41
  5. Réponses: 8
    Dernier message: 28/07/2005, 13h39

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