When i was developing app feature, i have got the weird Popup+ContentControl+ContentTemplate behavior. The code below raising stackoveflow exception without any reasons.
<Window x:Class="WpfExpo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
SizeToContent="WidthAndHeight">
<StackPanel>
<ToggleButton Content="Press Me" x:Name="MyToggleButton" />
<Popup
x:Name="MyPopup"
IsOpen="{Binding ElementName=MyToggleButton, Path=IsChecked}">
<ContentControl>
<ContentControl.ContentTemplate>
<DataTemplate>
<ContentPresenter />
</DataTemplate>
</ContentControl.ContentTemplate>
<TextBlock Text="Popup text" Background="White" Foreground="Black" />
</ContentControl>
</Popup>
</StackPanel>
</Window>
It happens when i use ContentControl inside Popup, but i can't realize it just for me or WPF bug.
This one works as expected:
<Window x:Class="WpfExpo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
SizeToContent="WidthAndHeight">
<StackPanel>
<ToggleButton Content="Press Me" x:Name="MyToggleButton" />
<Popup
x:Name="MyPopup"
IsOpen="{Binding ElementName=MyToggleButton, Path=IsChecked}">
<ContentControl>
<TextBlock Text="Popup text" Background="White" Foreground="Black" />
</ContentControl>
</Popup>
</StackPanel>
</Window>
Environment:
This is not a bug in the framework. It's a bug in your code. A logical error.
Important to know, the ContentPresenter
is the content host of the ContentControl
.
ContentControl.Content
is assigned (the TextBlock
).
ContentControl.ContentTemplate
is loaded and assigned to the internal ContentPresenter
of the ContentControl
. The new parent of the ContentPresenter
from the DataTemplate
is now the ContentPresenter
of the ContentControl
!
The DataTemplate
contains a ContentPresenter
. ContentPresenter
also contains a Content
and ContentTemplate
property. If they are not set then the ContentPresenter
will use the ContentSource
property to lookup the values from the templated parent. By default, ContenSource
is set to "Content"
. This tells the ContentPresenter
inside the DataTemplate
to get the value of the visual parent's properties that start with "Content"
. Which is the ContentControl.Content
and ContentPresenter.ContentTemplate
property.
The ContentPresenter
has now "inherited" the DataTemplate
from the ContentPresenter
of the ContentControl
.
The inherited DataTemplate
is applied to the ContentPresenter
.
Because the inherited DataTemplate
contains a ContentPresenter
the new parent of the new ContentPresenter
is the last ContentPresenter
: again it inherits the ControlTemplate
from the new parent ContentPresenter
and the infinite loop begins and the procedure repeats from 3)
==> In other words, you are adding a ContenPresenter
to the ContentPresenter
of the ContentControl
. the ContentPresenter
"inherits" the DataTemplate
which effectively adds another ContentPresenter
to the ContentPresenter
, which inherits the DataTemplate
to add another ContentPresenter
to the ContentPresenter
...
The question is, why would you add a ContentPresenter
to the DataTemplate
in the first place? The code doesn't make any sense. That logical error causes an infinite loop. WPF behaves totally normally.