2

I need to create a several styles that represent different point objects that all do the same thing. To be more specific, it is a bunch of ESRI MarkerSymbols that can either be a Circle, Square, Star, etc but that is probably not relevant to the specific problem.

Each point will behave exactly the same way when the user hovers or clicks on them - this is done through the Visual State Groups like so (I deleted several of the animations to save space:

<VisualStateManager.VisualStateGroups>
    <VisualStateGroup x:Name="SelectionStates">
        <VisualState x:Name="Unselected" />
        <VisualState x:Name="Selected">
            <Storyboard Storyboard.TargetName="shapeElement">
                <DoubleAnimation BeginTime="0:0:0" Duration="0:0:0.5" 
                                 Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)" 
                                 To="1" />
                <DoubleAnimation BeginTime="0:0:0" Duration="0:0:0.5"
                                 Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)"
                                 To="1" />
                ...................................................................
            </Storyboard>

        </VisualState>
    </VisualStateGroup>

    <VisualStateGroup x:Name="CommonStates">
        <VisualState x:Name="Normal">
            <Storyboard Storyboard.TargetName="shapeElement2">
                <DoubleAnimation BeginTime="0:0:0" Duration="0:0:0.1" 
                                 Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)"
                                 To="1" />
                <DoubleAnimation BeginTime="0:0:0" Duration="0:0:0.1"
                                 Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)" 
                                 To="1" />

                <ObjectAnimationUsingKeyFrames BeginTime="0:0:0.1" Duration="0:0:0" 
                                               Storyboard.TargetProperty="(UIElement.Visibility)">
                    <DiscreteObjectKeyFrame KeyTime="0:0:0">
                        <DiscreteObjectKeyFrame.Value>
                            <Visibility>Collapsed</Visibility>
                        </DiscreteObjectKeyFrame.Value>
                    </DiscreteObjectKeyFrame>
                </ObjectAnimationUsingKeyFrames>

            </Storyboard>
        </VisualState>

        <VisualState x:Name="MouseOver">
            <Storyboard Storyboard.TargetName="shapeElement2">

                <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="0:0:0.01"
                                               Storyboard.TargetProperty="(UIElement.Visibility)">
                    <DiscreteObjectKeyFrame KeyTime="00:00:00">
                        <DiscreteObjectKeyFrame.Value>
                            <Visibility>Visible</Visibility>
                        </DiscreteObjectKeyFrame.Value>
                    </DiscreteObjectKeyFrame>
                </ObjectAnimationUsingKeyFrames>

                <DoubleAnimation BeginTime="00:00:00" Duration="0:0:0.1"
                                 Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)" 
                                 To="1.75" />
                <DoubleAnimation BeginTime="00:00:00" Duration="0:0:0.1"
                                 Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)"
                                 To="1.75" />
                ...................................................................
            </Storyboard>
        </VisualState>
    </VisualStateGroup>

</VisualStateManager.VisualStateGroups>

Since I want to create several shapes that all will use this collection of Visual State Groups how do I turn it into a resource? In other words, how would I do this:

<esri:MarkerSymbol x:Key="CircleLocationPointMarker" OffsetX="6" OffsetY="6"  >
    <esri:MarkerSymbol.ControlTemplate>
        <ControlTemplate>
            <Grid >
                <Ellipse x:Name="shapeElement">
                    ..............................................
                </Ellipse>

                <Ellipse x:Name="shapeElement2"> 
                    ..............................................
                </Ellipse>

                <Border x:Name="LocationLabel">
                    ..............................................
                </Border>

                <VisualStateManager.VisualStateGroups>
                    ---HOW DO I USE A RESOURCE OR SEVERAL RESOURCES??---
                </VisualStateManager.VisualStateGroups>


            </Grid>
        </ControlTemplate>
    </esri:MarkerSymbol.ControlTemplate>
</esri:MarkerSymbol>

and say another one for a Square and a Star, and so on. Hope that makes sense.

Ernie S
  • 13,902
  • 4
  • 52
  • 79
  • 2
    Possible Duplicate: [Re-Use Animations in VisualStates](http://stackoverflow.com/questions/22666405/re-use-animations-in-visualstates) - I would also love to find a way of doing this. – Chris W. Jun 16 '14 at 14:44

1 Answers1

1

Ok, I can think of two possible solutions:

Number 1: Derive from the MarkerSymbol and add a public Shape property (or maybe better use Path), now you can develop just one ControlTemplate complete with VisualStates that uses the newly added property. Wherever you want to use you special marker you can provide a customized shape/geometry or you can further derive from it to create default shape markers:

<ControlTemplate TargetType="ShapedMarker" x:Key="ShapedMarkerDefaultTemplate">
    <Grid>
        <VisualStateManager.VisualStateGroups>...</...>
        <Path x:Name="shapeElement" Data="{TemplateBinding ShapeGeometry}"/>
        <Path x:Name="shapeElement2" Data="{TemplateBinding ShapeGeometry}"/>
        <Border x:Name="LocationLabel"/>
    </Grid>
</ControlTemplate>
<Style TargetType="ShapedMarker">
    <Setter Property="Template"
            Value="{StaticResource ShapedMarkerDefaultTemplate}"/>
</Style>

and code

public class ShapedMarker : MarkerSymbol
{
    public Geometry ShapeGeometry { get {...} set {...} }
    ...DependencyProperty ... "ShapeGeometry" ...

    public ShapedMarker(){ DefaultStyleKey = typeof(ShapedMarker); }
}

public class CircleLocationPointMarker : ShapedMarker
{
  public CircleLocationPointMarker(){this.ShapeGeometry = new EllipseGeometry();}
}

Number 2: Basically what I described here. You can write your own utility classes to generate VisualStates and all associated Animations programmatically, this saves you from writing the same markup over and over again. It is a tried and trusted approach and does not have a performance impact, the animations are only created once. However, this approach is not common and many developers are reluctant to try anything uncommon (an observation I even made in my own team). The markup could look like this:

<ControlTemplate ...>
    <Grid>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">
                <VisualState x:Name="Normal"
                    utils:AddAnimations.ScaledAndCollapsed="shapeElement2"/>
                <VisualState x:Name="MouseOver"
                    utils:AddAnimations.ScaledAndVisible="shapeElement2"/>
                <.../>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

        ...

    </Grid>
</ControlTemplate>

And you can even mix animations that are declared in xaml and animations that are added through your utility methods. The code will respect any existing animations.

Community
  • 1
  • 1
Martin
  • 5,714
  • 2
  • 21
  • 41