Share via


Collections of Items in Resources

Recently, I was trying to figure out how to reuse resources within multiple collections all defined in WPF XAML. For example, suppose I have the following:

 

<MeshGeometry3D.Positions>
<Point3D X="0" Y="0" Z="0"/>
<Point3D X="5" Y="0" Z="0"/>
<Point3D X="0" Y="0" Z="5"/>
</MeshGeometry3D.Positions>

 

What if I wanted to put the 3 Point3D instances in a resource and use them to populate a collection? Hmmm.... how about this?

 

<Window.Resources>

    <Point3D x:Key="PointA" X="0" Y="0" Z="0"/>
<Point3D x:Key="PointB" X="5" Y="0" Z="0"/>
<Point3D x:Key="PointC" X="0" Y="0" Z="5"/>
</Window.Resources>

 

<MeshGeometry3D.Positions>

    {StaticResource PointA}

    {StaticResource PointB}

    {StaticResource PointC}
</MeshGeometry3D.Positions>

 

Sure enough, that doesn't work. When you have something like this:

 

<SomeElement>
{Binding ... }
</SomeElement>

 

The "{Binding...}" string actually gets sent to the SomeElement type converter instead of being treated like a markup extension. 

 

So as jfo pointed out to me, I can do this:

 

<Window.Resources>

<Point3DCollection x:Key="MyPoints">

<Point3D X="0" Y="0" Z="0"/>
<Point3D X="5" Y="0" Z="0"/>
<Point3D X="0" Y="0" Z="5"/>

</Point3DCollection>
</Window.Resources>

<MeshGeometry3D.Positions="{StaticResource MyPoints}">

Ok, not bad, but now, what if I want to share those points on multiple resources (I know this is getting contrived but I can imagine there being a reason to want to do this to avoid duplication in some scenario), I can't go back and do this:

<Window.Resources>

<Point3D x:Key="PointA" X="0" Y="0" Z="0"/>
<Point3D x:Key="PointB" X="5" Y="0" Z="0"/>
<Point3D x:Key="PointC" X="0" Y="0" Z="5"/>
<Point3DCollection x:Key="MyPoints">

{StaticResource PointA}
{StaticResource PointB}
{StaticResource PointC}
</Point3DCollection>
<Point3DCollection x:Key="MyOtherPoints">

{StaticResource PointA}
{StaticResource PointC}
</Point3DCollection>
</Window.Resources>

So how would I do this in such a way that I can avoid duplicating those Point3D values?

Well, off to Chuck I go. His answer? Element Syntax for Markup Extensions:

<Window.Resources>
<Point3D x:Key="First" X="0" Y="0" Z="0"/>
<Point3D x:Key="Second" X="5" Y="0" Z="0"/>
<Point3D x:Key="Third" X="0" Y="0" Z="5"/>
<Point3DCollection x:Key="MyPoints">
<StaticResource ResourceKey="First"/>
<StaticResource ResourceKey="Second"/>
<StaticResource ResourceKey="Third"/>
</Point3DCollection>

<Point3DCollection x:Key="MyOtherPoints">

<StaticResource ResourceKey="First"/>
<StaticResource ResourceKey="Third"/>
</Point3DCollection>
</Window.Resources>

I thought that was pretty cool. I wasn't aware of that syntax. Very useful. I've also seen it with Binding where this:

<TextBlock FontSize="12" Foreground="Red" Text="{Binding XPath=@ISBN}"/>

Is replaced by this:

<TextBlock FontSize="12" Foreground="Red">
<TextBlock.Text>
<Binding XPath="@ISBN"/>
</TextBlock.Text>
</TextBlock>

Cool and useful!