wpfpopupcontentcontrolcontenttemplate

WPF bug? Popup,ContentControl and ContentTemplate raising stack overflow exception


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>

Works

Environment:


Solution

  • 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.

    1. ContentControl.Content is assigned (the TextBlock).

    2. 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!

    3. 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.

    4. The ContentPresenter has now "inherited" the DataTemplate from the ContentPresenter of the ContentControl.

    5. The inherited DataTemplate is applied to the ContentPresenter.

    6. 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.