Path only appears once when applied in DataTemplate

Tags: c# xaml uwp
Question!

I need to reuse some vector images. I've implemented this using styles for a path setting the Data property.

When this style is applied in a DataTemplate set to a ListView, only the first item actually shows the path. The Path is visible in live outline during my debugging session. Design time it does show in each item.

I have already tried to make the style unshared using x:Shared="False" however this causes the hard to understand XBF generation error code 0x09c4. compile error.

<!-- Path Style defined in a seperate resource dictionary -->
<Style x:Key="Icon" TargetType="Path">
    <Setter Property="Data" Value="F1 M32,32z M0,0z M8,7L8,8 8,9 5,9 4,9 4,10 4,24 4,25 5,25 27,25 28,25 28,24 28,10 28,9 27,9 24,9 24,8 24,7 23,7 19,7 18,7 18,8 18,9 14,9 14,8 14,7 13,7 9,7 8,7z M10,9L12,9 12,10 12,11 13,11 19,11 20,11 20,10 20,9 22,9 22,10 22,11 23,11 26,11 26,23 6,23 6,11 9,11 10,11 10,10 10,9z"/>
</Style>

<!-- DataTemplate defined in a seperate resource dictionary-->
<DataTemplate x:Key="ListViewItem">
    <ViewBox>
        <Path Style="{StaticResource Icon}" Fill="{StaticResource IconBrush}"/>
    </ViewBox>
</DataTemplate>

<!-- DataTemplate applied on a page -->
<ListView
    ItemTemplate="{StaticResource ListViewItem}"
    ItemsSource={Binding Items}>
</ListView>

Does anyone have any ideas about what might cause this behaviour and how it can be solved?



Answers
This is a known issue since the days with Silverlight. When used inside a style, the Path will only be instantiated once. Unlike in WPF, there's no x:Shared="False" to force creating a new instance every time it's requested.

That leaves you with three other options.

First, you can use the Path directly inside your DataTemplate.

<DataTemplate x:Key="ListViewItem">
    <Viewbox>
        <Path Data="F1 M32,32z M0,0z M8,7L8,8 8,9 5,9 4,9 4,10 4,24 4,25 5,25 27,25 28,25 28,24 28,10 28,9 27,9 24,9 24,8 24,7 23,7 19,7 18,7 18,8 18,9 14,9 14,8 14,7 13,7 9,7 8,7z M10,9L12,9 12,10 12,11 13,11 19,11 20,11 20,10 20,9 22,9 22,10 22,11 23,11 26,11 26,23 6,23 6,11 9,11 10,11 10,10 10,9z" Fill="Red"/>
    </Viewbox>
</DataTemplate>

For more flexibility, you can also use a ContentControl instead.

<Style x:Key="Icon" TargetType="ContentControl">
    <Setter Property="ContentTemplate">
        <Setter.Value>
            <DataTemplate>
                <Path Fill="Red" Data="F1 M32,32z M0,0z M8,7L8,8 8,9 5,9 4,9 4,10 4,24 4,25 5,25 27,25 28,25 28,24 28,10 28,9 27,9 24,9 24,8 24,7 23,7 19,7 18,7 18,8 18,9 14,9 14,8 14,7 13,7 9,7 8,7z M10,9L12,9 12,10 12,11 13,11 19,11 20,11 20,10 20,9 22,9 22,10 22,11 23,11 26,11 26,23 6,23 6,11 9,11 10,11 10,10 10,9z"/>
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>

<DataTemplate x:Key="ListViewItem">
    <Viewbox>
        <ContentControl Style="{StaticResource Icon}"/>
    </Viewbox>
</DataTemplate>

The last one is probably the best but it will require some work to change the Data property to a more specific PathGeometry.

<Style x:Key="Icon" TargetType="Path">
    <Setter Property="Data">
        <Setter.Value>
            <PathGeometry FillRule="EvenOdd">
                <PathFigure IsClosed="True" StartPoint="0,0">
                    <LineSegment Point="xxx,xxx" />
                    <LineSegment Point="xxx,xxx" />
                </PathFigure>
            </PathGeometry>
        </Setter.Value>
    </Setter>
</Style>
By : Justin XL


This video can help you solving your question :)
By: admin