Search code examples
wpfxamlmefreleaselogical-tree

How to debug a "Specified element is already the logical child of another element" in the release


I know I'm supposed to post a very specific question with a code sample, but I wouldn't know where to start with this:

While running my app in Visual Studio it is ok, both in Debug and in Release modes. But when I create an InstallShield installer, in other computers I get an Exception:

System.Windows.Threading.Dispatcher WPF Specified element is already the logical child of another element. Disconnect it first

I've seen tons of posts regarding this issue in StackOverflow and in other webs, but there is no reference o this happening only in the installed package.

My question is double (sorry for that too):

  1. How could I possibly debug such an issue? I mean, specifically if possible (not a generic runtime debug)
  2. What kind of exception can I catch that gives me more information on the error? I'm displaying a MessageBox that shows a ReflectionTypeLoadException. I'd love to see which element is the one with the "double parent" or "double child".

To complicate things further, the app runs fine in the computers I use for development, but it crashes with this exception in others (say, my father's and sister's computers).

ANY clue will be appreciated and duely upvoted. Thanks

-----------------------------------EDIT-------------------------------------

I managed to corner the troublesome child to the TextBlock named "textAvisosSeccion" inside the ListView's ItemTemplate:

<ListView ItemsSource="{Binding Secciones}" Background="{Binding MiColor}"
          Style="{StaticResource NavigationMenuStyle}"
          IsSynchronizedWithCurrentItem="True"
          SelectedItem="{Binding SeccionActiva}"
          Margin="0" MinWidth="{Binding RelativeSource={RelativeSource
          AncestorType=ListBoxItem}, Path=ActualWidth}" HorizontalContentAlignment="Stretch">
             <ListView.ItemTemplate>
                <DataTemplate>
                     <DockPanel LastChildFill="True" HorizontalAlignment="Stretch">
                           <Grid DockPanel.Dock="Right" Margin="2,2,8,2"
                            Visibility="{Binding ElementName=textAvisosSeccion, Path=Visibility, FallbackValue=Collapsed}">
                                 <Ellipse Height="25" Width="25" VerticalAlignment="Center"
                                 Stroke="WhiteSmoke" StrokeThickness="1" Fill="OrangeRed"/>
                                 <TextBlock x:Name="textAvisosSeccion" FontSize="12"
                                  FontWeight="Medium" Foreground="WhiteSmoke"
                                  VerticalAlignment="Center" HorizontalAlignment="Center" TextAlignment="Center" Style="{StaticResource TextBlockNullZeroCollapsedStyle}"
                                  Text="{Binding Value.Avisos}"/>
                             </Grid>

                          <TextBlock DockPanel.Dock="Left" Text="{Binding Metadata.NombreTraducido}" Margin="8,2" VerticalAlignment="Center" HorizontalAlignment="Stretch" TextAlignment="Center"/>

                     </DockPanel>
                  </DataTemplate>
               </ListView.ItemTemplate>
           </ListView>

<Style x:Key="TextBlockNullZeroCollapsedStyle" TargetType="TextBlock">
    <Style.Triggers>
        <Trigger Property="Text" Value="">
            <Setter Property="Visibility" Value="Collapsed"/>
        </Trigger>
        <Trigger Property="Text" Value="0">
            <Setter Property="Visibility" Value="Collapsed"/>
        </Trigger>
    </Style.Triggers>
</Style>

Check out the binding Text="{Binding Value.Avisos}". The ListView is bound to a collection of Lazy<T> imported with MEF, in which T has the "Avisos" property. The other TexkBlock is binding to the Lazy<T>'s Metadata and it's fine.

Besides the reasons why I am binding to a Lazy's value (which instantiates the object, losing the lazy's advantage), why am I getting a "Specified element is already the logical child of another element" exception because of this?!?!?

The "Avisos" property is just an integer inside a ViewModel (which is not inheriting from UIElement).

EDIT #2:

Exceptions like this one and others (problems in styles, MEF composition issues, etc.) were not being thrown in VS2012 because it that computer the .NET Framework 4.5 was installed. Even when all the projects targeted Framework 4.0.

If you are developing for 4.0 get an old machine with Vista, make sure you have 4.0 installed and use VS2010; it's the only way to make sure.


Solution

  • This is not a real answer to the question, but the solution I found to the problem: install .NET Framework 4.5 in the client machine, and the app runs like a charm.

    After removing the troublesome TextBlock, the application opened but threw the same exception in a lot of places, but with no apparent reason: some ViewModels and Views worked fine, others did not. Of course, they are all built in the same way, so no explanation there.

    I found this SO question referring this issue, but with no good answer:

    Did WPF 4.5 parent-child behavior change: we can now add a child to another parent without exception?

    For this guy it created a problem instead of solving it. A scary question arises though: how can we know if in the next Framework version everything will work the same? Maybe this was a bug in 4.0 that was fixed in 4.5, and they don't want to talk about it.

    Another major issue was that the exception gives no real information about which elements have the problem, so it makes it almost useless to debug. I found in some forum that this was posted to Microsoft as an improvement suggestion and they repeatedly rejected it.

    Hope this helps someone, and I also hope that someone tells me how to dig deeper into the exepction to know which element is complainig.

    Copying EDIT #2 here too:

    Exceptions like this one and others (problems in styles, MEF composition issues, etc.) were not being thrown in VS2012 because it that computer the .NET Framework 4.5 was installed. Even when all the projects targeted Framework 4.0.

    If you are developing for 4.0 get an old machine with Vista, make sure you have 4.0 installed and use VS2010; it's the only way to make sure.