Объявление коллекции групп VisualStateManager в качестве ресурса в шаблоне элемента управления

Мне нужно создать несколько стилей, представляющих разные точечные объекты, которые делают одно и то же. Чтобы быть более конкретным, это набор символов маркеров ESRI, который может быть кругом, квадратом, звездой и т. д., но, вероятно, не имеет отношения к конкретной проблеме.

Каждая точка будет вести себя точно так же, когда пользователь наводит на них курсор или щелкает — это делается с помощью групп визуального состояния (я удалил несколько анимаций для экономии места:

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

Поскольку я хочу создать несколько фигур, которые будут использовать эту коллекцию групп визуальных состояний, как мне превратить ее в ресурс? Другими словами, как бы я это сделал:

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

и произнесите еще один для Квадрата и Звезды, и так далее. Надеюсь, это имеет смысл.


person Ernie S    schedule 14.06.2014    source источник
comment
Возможный дубликат: Повторное использование анимации в VisualStates. Я также хотел бы найти способ делать это.   -  person Chris W.    schedule 16.06.2014


Ответы (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: в основном то, что я описал здесь. Вы можете написать свои собственные служебные классы для создания 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, и анимации, добавленные с помощью ваших служебных методов. Код будет учитывать любые существующие анимации.

person Martin    schedule 18.06.2014