将VisualStateManager组集合声明为控件模板中的资源

时间:2014-06-14 17:08:28

标签: visual-studio silverlight xaml controltemplate arcobjects

我需要创建几个代表不同点对象的样式,它们都做同样的事情。更具体地说,它是一堆ESRI MarkerSymbols,可以是Circle,Square,Star等,但这可能与特定问题无关。

当用户悬停或点击它们时,每个点的行为都会完全相同 - 这是通过视觉状态组完成的(我删除了几个动画以节省空间:

<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>

由于我想要创建几个所有将使用此Visual Group Groups集合的形状,如何将其转换为资源?换句话说,我该怎么做:

<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>

并为Square和Star说另一个,依此类推。希望这是有道理的。

1 个答案:

答案 0 :(得分:1)

好的,我可以想到两种可能的解决方案:

数字1:MarkerSymbol派生并添加公共 Shape 属性(或者更好地使用Path),现在您只需开发一个ControlTemplate VisualStates使用新添加的属性。无论您想在何处使用特殊标记,您都可以提供自定义的形状/几何图形,或者您可以从中进一步派生它以创建默认的形状标记:

<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>

和代码

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();}
}

数字2: 基本上我所描述的here。您可以编写自己的实用程序类来以编程方式生成VisualStates和所有关联的Animations,这样可以避免一遍又一遍地编写相同的标记。它是一种经过尝试和信任的方法,没有性能影响,动画只创建一次。然而,这种方法并不常见,很多开发人员都不愿意尝试任何不寻常的事情(我甚至在我自己的团队中做过观察)。 标记可能如下所示:

<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>

您甚至可以混合使用xaml声明的动画和通过实用程序方法添加的动画。该代码将尊重任何现有的动画。