WPF Multiple ContentPresenters same content - Only 1 is populated

51 views Asked by At

Here's an extremely basic example of what I'm trying to do but does not work:

<StackPanel>
    <StackPanel.Resources>
        <Grid x:Key="MyYellowEllipse">
            <Ellipse Width="50" Height="50" Fill="Yellow" />
        </Grid>
        <Grid x:Key="MyBlueEllipse">
            <Ellipse Width="50" Height="50" Fill="Blue" />
        </Grid>
    </StackPanel.Resources>
    <ContentPresenter Content="{StaticResource MyYellowEllipse}" />
    <ContentPresenter Content="{StaticResource MyBlueEllipse}" />
    <ContentPresenter Content="{StaticResource MyYellowEllipse}" />
    <ContentPresenter Content="{StaticResource MyBlueEllipse}" />
    <ContentPresenter Content="{StaticResource MyYellowEllipse}" />
    <ContentPresenter Content="{StaticResource MyBlueEllipse}" />
</StackPanel>

Example Output

For some reason when I do this, only the last two are populated (though space is left for the other). I would expect to be able to reuse the same content in multiple content presenters.

Why can't I do this, and more importantly, how should I be doing this instead if I want to achieve this.

I've built a bunch of custom glyphs using Path and Polygon objects in grids in a resource dictionary and I'd like to display them in multiple places in my app but they're only showing up in one usage (just like my example). I thought ContentPresenter was meant for this.

EDIT: It's a solution

@emoacht pointed out in the comments that adding x:Shared="False" to the Grid in the resource definitions will fix the problem. I'm going to use this solution for now.

For my own edification; however, I'd love if someone could explain to me A.) Why that's needed and B.) What the more appropriate solution to reusing a <Grid> with a bunch of <Polygon>s in it would be.

1

There are 1 answers

1
mm8 On

@emoacht pointed out in the comments that adding x:Shared="False" to the Grid in the resource definitions will fix the problem. I'm going to use this solution for now. For my own edification; however, I'd love if someone could explain to me

A.) Why that's needed

Because the default resource-retrieval behavior in WPF is to share an instance of a XAML resource for all requests. You can read more about this in the docs.

and B.) What the more appropriate solution to reusing a <Grid> with a bunch of s in it would be.

You could for an example define MyYellowEllipse and MyBlueEllipse as a custom types:

public class MyYellowEllipse : Grid
{
    public MyYellowEllipse()
    {
        Children.Add(new Ellipse() { Width = 50, Height = 50, Fill = Brushes.Yellow });
    }
}

public class MyBlueEllipse : Grid
{
    public MyBlueEllipse()
    {
        Children.Add(new Ellipse() { Width = 50, Height = 50, Fill = Brushes.Blue });
    }
}

...and use them in your XAML markup like this without involving any resources:

<StackPanel>
    <local:MyYellowEllipse />
    <local:MyBlueEllipse />
    <local:MyYellowEllipse />
    <local:MyBlueEllipse />
    <local:MyYellowEllipse />
    <local:MyBlueEllipse />
</StackPanel>

You could obviously also create a base class called MyEllipse or something for code-sharing reasons but you get the point.