The life of a Visual must be very sad since they can only have one parent.  

This means you will get an error or unexpected behaviour if you somehow try and give a given Visual more than one parent.

What's a Visual?

Visual is a base class which controls - pretty much any XAML object which you can see in your view inherits from Visual.  

In the greater scheme of things the difference between Visual, UIElement and Control is usually rather academic.

Let's take a quick look at the inheritance tree for Button ( from MSDN ):

System.Object
  System.Windows.Threading.DispatcherObject
    System.Windows.DependencyObject
      System.Windows.Media.Visual
        System.Windows.UIElement
          System.Windows.FrameworkElement
            System.Windows.Controls.Control
              System.Windows.Controls.ContentControl
                System.Windows.Controls.Primitives.ButtonBase
                  System.Windows.Controls.Button

All controls inherit from Visual but controls you type into or click are a bit further up that inheritance tree.  Something which works on it's own as a stand alone sort of thing will be at least a UIElement.  Something inheriting directly from Visual is a discrete object which will go into something else in order to appear on your screen.
As the name Visual implies, it's the kind of thing which has a Visual effect inside a more complicated control ( or UIElement ) .

Visuals  arguably behave rather badly compared to controls when you add them to a second parent because something weird happens.

But this is getting ahead of things.

What Happens?

That's the idea of the sample which you can download here.

This sample uses a set of controls to illustrate the bad things which can happen if you forget the one parent rule.

If you spin the sample up with an f5 you see this:

The UI could probably do with a bit of work before going live ;^)

We're going to use this for two experiments.

Experiment One

There are two vertical halves to this window.  Two columns,

The left half is our first experiment.

There's a button called It which is that big button says "It" on..... ahem.... it.

Below is another button which says "Add It to grid row zero".

It is already in a Grid so what this is going to try and do is add It to another grid.

Click the Add It... button.

Bang.

You get an error.

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

This demonstrates what happens with a Control which already has a parent is added to the children of anything in the visual tree with out first using "Children.Remove()" so it has no parent.

With Controls you get an error.

In a way this is preferable to Visuals.

Experiment Two

The right half of the screen is a bit odd.  There are two textblocks - tb1 and tb2 which are labelled as such.  When you click the button "Add Inlines" it creates some Inlines ( a Run is a type of Inline ) and adds them first to tb1 then to tb2.

When you click it you see this:

There is no error but those InLines all end up in tb2 and not in tb1.

The text you see there "First Parent of LineOne: tb1" is produced after the lineOne inline is added to tb1, just to prove that it had that control as a parent at one time.

If this is a bit confusing then the code will probably make things clearer.

MarkUp

This is how that screen is put together:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <Grid Name="Grid0" Grid.Row="0"/>
    <Grid Name="Grid1" Grid.Row="1">
        <Button Name="it" FontSize="30">It</Button>
    </Grid>
    <Button Grid.Row="2" Height="30" Margin="10" Click="Button_Click">Add it to grid row zero</Button>
    <!--  -->
    <StackPanel Grid.Column="1">
        <TextBlock Text="tb1:"/>
        <TextBlock x:Name="tb1"/>
    </StackPanel>
    <StackPanel Grid.Row="1" Grid.Column="1">
        <TextBlock Text="tb2:"/>
        <TextBlock Name="tb2"/>
    </StackPanel>
    <Button Grid.Row="2" Height="30" Margin="10" Click="Button_Click_1" Grid.Column="1">Add Inlines</Button>
    <TextBlock Name="FirstParent" Grid.Row="2" Grid.Column="1" VerticalAlignment="Top"/>
    <TextBlock Name="SecondParent" Grid.Row="2" Grid.Column="1" VerticalAlignment="Bottom"/>
</Grid>

You can see there are two columns which the two experiments are arranged in.
Things to particularly note are:
Those labelled textblocks tb1 and tb2.
The TextBlocks FirstParent and SecondParent which will be used to show those messages above and below the button on  the right.

Code Behind

Let;s split these two parts up.

Left Column

This is the experiment with a Button control.

private void Button_Click(object sender, RoutedEventArgs e)
{
    Grid0.Children.Add(it);
}

That grabs the button it and tries to add it to Grid0 which is inside row 0 of the root grid.
It is already insode Grid1 which is it's parent when the window loads.
When you click the button, it errors because adding a control to a second children collection isn't allowed and produces an error. 

Right Column

There's a bit more to  the code here:

private void Button_Click_1(object sender, RoutedEventArgs e)
{
    Inline lb = new LineBreak();
    Run lineOne = new Run("Line one");
    Run lineTwo = new Run("Line Two");
    tb1.Inlines.Add(lineOne);
    tb1.Inlines.Add(lb);
    tb1.Inlines.Add(lineTwo);
 
    FirstParent.Text = "First Parent of lineOne: " + ((TextBlock)lineOne.Parent).Name;
 
    tb2.Inlines.Add(lineOne);
    tb2.Inlines.Add(lb);
    tb2.Inlines.Add(lineTwo);
 
    SecondParent.Text = "Second Parent of lineOne: " + ((TextBlock)lineOne.Parent).Name;
}

An Inline and a couple of Runs are newed up.
They're added to tb1.
The parent of one of them id found and displayed in  the TextBlock which goes above the button.
This proves for certain at that point in time lineOne was absolutely definitely a child of tb1. 
They are then added to tb2 and something pretty strange happens.
They are no longer children of tb1 ( because they can only have one parent ) but no error is thrown so the code just carries on.
The parent of that same inline is found and displayed in the textblock below the button.
You don't really need to see that to prove the parent has changed because you can see the inlines in tb2 but this absolutely proves wpf thinks the parent of those inlines is now tb2.

Implications

You're probably not going to be adding a button to more than one parent in code, but if you did so you will get an error reminds you that this is a problem.

What is much more likely is that you will overlook something or other is actually a visual when you make it a resource.

It then only appears the last place you used it because it can only have one parent.

If this happens to you and gives you no error, you now know why.

See Also


This article is part of the WPF Tips Series, if WPF is your area of interest then you will probably find other useful articles there.