tags:

views:

963

answers:

4

Hi all,

I have a Path (a star figure):

<Path x:Name="NiceStar" StrokeThickness="10" Stroke="#ff000000" StrokeMiterLimit="1" Data="F1 M 126.578613,11.297852 L 162.373535,83.825684 L 242.412598,95.456055 L 184.495605,151.911133 L 198.167480,231.626953 L 126.578613,193.990234 L 54.988770,231.626953 L 68.661621,151.911133 L 10.744629,95.456055 L 90.783691,83.825684 L 126.578613,11.297852 Z">
 <Path.Fill>
  <RadialGradientBrush MappingMode="Absolute" GradientOrigin="390.395508,448.130371" Center="390.395508,448.130371" RadiusX="113.034821" RadiusY="113.034821">
   <RadialGradientBrush.Transform>
    <MatrixTransform Matrix="1,0,-0,-1,-263.816895,569.592773" />
   </RadialGradientBrush.Transform>
   <GradientStop Offset="0" Color="#ff00ff00"/>
   <GradientStop Offset="1" Color="#ff006736"/>
  </RadialGradientBrush>
 </Path.Fill>
</Path>

Now I want to duplicate this Path several times (just refering to "NiceStar"). Can I do this in pure XAML?

I can use it once, by doing this:

<Decorator Child="{StaticResource star}" />

However, I cannot duplicate this line. My compiler says:

Specified element is already the logical child of another element. Disconnect it first.
+3  A: 

Sure, just define a Style for the path and then you can reuse it as a static resource:

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&gt;
<Page.Resources>
    <Style x:Key="StarStyle" TargetType="Path">
    <Setter>
        <Setter.Property>Fill</Setter.Property>
        <Setter.Value>                
             <RadialGradientBrush MappingMode="Absolute"
              GradientOrigin="390.395508,448.130371" Center="390.395508,448.130371"
              RadiusX="113.034821" RadiusY="113.034821">
             <RadialGradientBrush.Transform>
                 <MatrixTransform Matrix="1,0,-0,-1,-263.816895,569.592773" />
             </RadialGradientBrush.Transform>
             <GradientStop Offset="0" Color="#ff00ff00"/>
             <GradientStop Offset="1" Color="#ff006736"/>
             </RadialGradientBrush>
         </Setter.Value> 
    </Setter>
    <Setter Property="StrokeThickness" Value="10" />
    <Setter Property="Stroke" Value="#ff000000" />
    <Setter Property="StrokeMiterLimit" Value="1" />
    <Setter Property="Data" Value="F1 M 126.578613,11.297852 L 162.373535,83.825684 L 242.412598,95.456055 L 184.495605,151.911133 L 198.167480,231.626953 L 126.578613,193.990234 L 54.988770,231.626953 L 68.661621,151.911133 L 10.744629,95.456055 L 90.783691,83.825684 L 126.578613,11.297852 Z"/>
    </Style>
</Page.Resources>
<StackPanel>  
    <Path Style="{StaticResource StarStyle}" />
    <Path Style="{StaticResource StarStyle}" />
</StackPanel>
</Page>
Mark Heath
That's sad... I was working on the style when the header said an answer had been posted. I wanted to finish my answer before loading. Good job, you beat me to the punch! :-)
Josh G
Thanks anyway for your answer!
Robbert Dam
+3  A: 

Create a style.

<Style x:Key="NiceStarPath" TargetType="{x:Type Path}">
    <Setter Property="StrokeThickness" Value="10"/>
    <Setter Property="Stroke" Value="#FF000000"/>
    <Setter Property="StrokeMiterLimit" Value="1"/>
    <Setter Property="Data" Value="F1 M 126.578613,11.297852 L 162.373535,83.825684 L 242.412598,95.456055 L 184.495605,151.911133 L 198.167480,231.626953 L 126.578613,193.990234 L 54.988770,231.626953 L 68.661621,151.911133 L 10.744629,95.456055 L 90.783691,83.825684 L 126.578613,11.297852 Z"/>
    <Setter Property="Fill">
        <Setter.Value>
            <RadialGradientBrush MappingMode="Absolute" GradientOrigin="390.395508,448.130371" Center="390.395508,448.130371" RadiusX="113.034821" RadiusY="113.034821">
                <RadialGradientBrush.Transform>
                    <MatrixTransform Matrix="1,0,-0,-1,-263.816895,569.592773" />
                </RadialGradientBrush.Transform>
                <GradientStop Offset="0" Color="#ff00ff00"/>
                <GradientStop Offset="1" Color="#ff006736"/>
            </RadialGradientBrush>
        </Setter.Value>
    </Setter>
</Style>

...

<Path Style="{StaticResource NiceStarPath}"/>
Josh G
+1  A: 

In a related note, (although probably not directly answering your question), you can also declare a FrameworkElement as a Resource, give it a key, and as long as you add x:Shared="False" you can access the resource again and again in code.

Here's a pseudocoded example:

<Window ....>
   <Window.Resources>
      <Ellipse x:Key="ReusableEllipse" x:Shared="False" ...>
         <Ellipse.Fill>
            <!--STUFF-->
         </Ellipse.Fill>
      </Ellipse>
   </Window.Resources>
   <Canvas x:Name="drawCanvas" Background="White"/>
</Window>

Then, in code, you can access the resourced shape and reuse it as many times as needed.

Ellipse tempRect = (Ellipse)FindResouce("ReusableEllipse");
Drew McGhie
A: 

I would turn the path into a DrawingBrush. This is really easy to do in blend, just select the path, Tools > Make Brush Resource > Make DrawingBrush Resource. Then you'll have the brush in your resources, ready to reuse. I expect the performance of this will be pretty good, since the brush is non-interactive and reusable.

Here is the XAML:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="640" Height="480">
    <Window.Resources>
     <DrawingBrush x:Key="NiceStarBrush" Viewbox="0,0,250,240" ViewboxUnits="Absolute">
      <DrawingBrush.Drawing>
       <GeometryDrawing Geometry="F1M126.578613,11.297852L162.373535,83.825684 242.412598,95.456055 184.495605,151.911133 198.16748,231.626953 126.578613,193.990234 54.98877,231.626953 68.661621,151.911133 10.744629,95.456055 90.783691,83.825684 126.578613,11.297852z">
        <GeometryDrawing.Brush>
         <RadialGradientBrush MappingMode="Absolute" Center="390.395508,448.130371" GradientOrigin="390.395508,448.130371" RadiusX="113.034821" RadiusY="113.034821">
          <RadialGradientBrush.Transform>
           <MatrixTransform Matrix="1,0,0,-1,-263.816895,569.592773"/>
          </RadialGradientBrush.Transform>
          <GradientStop Color="Lime" Offset="0"/>
          <GradientStop Color="#FF006736" Offset="1"/>
         </RadialGradientBrush>
        </GeometryDrawing.Brush>
        <GeometryDrawing.Pen>
         <Pen Brush="Black" DashCap="Flat" EndLineCap="Flat" LineJoin="Miter" MiterLimit="1" StartLineCap="Flat" Thickness="10">
          <Pen.DashStyle>
           <DashStyle/>
          </Pen.DashStyle>
         </Pen>
        </GeometryDrawing.Pen>
       </GeometryDrawing>
      </DrawingBrush.Drawing>
     </DrawingBrush>
    </Window.Resources>
    <Grid x:Name="LayoutRoot">
     <Rectangle Margin="181,115,0,0" Fill="{DynamicResource NiceStarBrush}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="50" Height="46" />
    </Grid>
</Window>

Another option is to turn wrap the path into an imagesource using DrawingImage

Rob Fonseca-Ensor