相当于WPF样式的UWP触发器

问题描述 投票:0回答:1

我创建了一个可以在WPF中使用的控件,现在尝试移植到UWP。

[该控件公开一个布尔属性,当设置为true时,我通过带有“永远”的RepeatBehavior的故事板更改路径(描边)的背景颜色。

阅读了许多文章之后,我了解UWP使用了VisualStates,Interactivity等,但是没有触发器。我已经尝试过修改代码,但没有获取背景来更改/设置动画。

WPF中ControlTemplate的一部分

 <Path Fill="Transparent"
      Stroke="{TemplateBinding Outline}"
      StrokeThickness="{TemplateBinding Thickness}"
      StrokeDashCap="Flat"
      x:Name="OuterRing">
    <Path.Data>
        <PathGeometry>
            <PathGeometry.Figures>
                <PathFigureCollection>
                    <PathFigure x:Name="OutlineFigurePart">
                        <PathFigure.Segments>
                            <PathSegmentCollection>
                                <ArcSegment x:Name="OutlineArcPart" IsLargeArc="True" SweepDirection="Clockwise"/>
                            </PathSegmentCollection>
                        </PathFigure.Segments>
                    </PathFigure>
                </PathFigureCollection>
            </PathGeometry.Figures>
        </PathGeometry>
    </Path.Data>

    <Path.Style>
        <Style TargetType="Path">
            <Style.Triggers>
                <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=controls:MyControl}, Path=IsValueOutOfRange}" Value="True">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <ColorAnimation To="Red" 
                                                AutoReverse="True"
                                                Duration="0:0:0.8" 
                                                RepeatBehavior="Forever"
                                                Storyboard.TargetProperty="(Path.Stroke).(SolidColorBrush.Color)"
                                                Storyboard.TargetName="OuterRing"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                    <DataTrigger.ExitActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <ColorAnimation To="LightGray" 
                                                Storyboard.TargetProperty="(Path.Stroke).(SolidColorBrush.Color)" 
                                                Duration="0:0:0.8"
                                                FillBehavior="Stop"
                                                Storyboard.TargetName="OuterRing"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.ExitActions>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Path.Style>
</Path>

视图中使用的控件(XAML)

<controls:MyControl Width="48" 
                    Height="48"
                    Header="My Header"
                    IsValueOutOfRange="{x:Bind ValueOutOfRange" />
  1. ValueOutOfRange从ViewModel设置为'True'时,Path.Stroke颜色应在'OuterRing'上进行动画处理]
  2. ValueOutOfRange从ViewModel设置为'False'时,Path.Stroke颜色应恢复为正常。

UWP中ControlTemplate的一部分

<Path Fill="Transparent"
      Stroke="{TemplateBinding Outline}"
      StrokeThickness="{TemplateBinding Thickness}"
      StrokeDashCap="Flat"
      x:Name="OuterRing">
    <Path.Data>
        <PathGeometry>
            <PathGeometry.Figures>
                <PathFigureCollection>
                    <PathFigure x:Name="OutlineFigurePart">
                        <PathFigure.Segments>
                            <PathSegmentCollection>
                                <ArcSegment x:Name="OutlineArcPart" IsLargeArc="True" SweepDirection="Clockwise"/>
                            </PathSegmentCollection>
                        </PathFigure.Segments>
                    </PathFigure>
                </PathFigureCollection>
            </PathGeometry.Figures>
        </PathGeometry>
    </Path.Data>

    <interactivity:Interaction.Behaviors>
        <core:DataTriggerBehavior Binding="{TemplateBinding IsValueOutOfRange}" Value="True" ComparisonCondition="Equal">
            <media:ControlStoryboardAction ControlStoryboardOption="Play">
                <media:ControlStoryboardAction.Storyboard>
                    <Storyboard>
                        <ColorAnimation
                            To="Red" 
                            Storyboard.TargetName="OuterRing" 
                            Storyboard.TargetProperty="(Path.Stroke).(SolidColorBrush.Color)" 
                            AutoReverse="True" 
                            Duration="0:0:8"
                            RepeatBehavior="Forever" />
                    </Storyboard>
                </media:ControlStoryboardAction.Storyboard>
            </media:ControlStoryboardAction>
        </core:DataTriggerBehavior>
    </interactivity:Interaction.Behaviors>
</Path>
xaml uwp uwp-xaml
1个回答
0
投票

在UWP中,更常见的方法是使用VisualStateManager处理:

根据您的代码,可以像这样重写:

隐藏代码

public bool IsValueOutOfRange
{
    get { return (bool)GetValue(IsValueOutOfRangeProperty); }
    set { SetValue(IsValueOutOfRangeProperty, value); }
}

// Using a DependencyProperty as the backing store for IsValueOutOfRange.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsValueOutOfRangeProperty =
    DependencyProperty.Register("IsValueOutOfRange", typeof(bool), typeof(PathCustomControl), new PropertyMetadata(false,new PropertyChangedCallback(IsValueOutofRange_Changed)));

private static void IsValueOutofRange_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    if(e.NewValue is bool isOut)
    {
        var instance = d as PathCustomControl;
        if (isOut)
            VisualStateManager.GoToState(instance, "Invalid", false);
        else
            VisualStateManager.GoToState(instance, "Normal", false);
    }
}

模板

<ControlTemplate TargetType="local:PathCustomControl">
    <Grid x:Name="rootGrid">
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="Common">
                <VisualState x:Name="Invalid">
                    <Storyboard>
                        <ColorAnimation To="Red" 
                                AutoReverse="True"
                                Duration="0:0:0.8" 
                                RepeatBehavior="Forever"
                                Storyboard.TargetProperty="(Path.Stroke).(SolidColorBrush.Color)"
                                Storyboard.TargetName="OuterRing"/>
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="Normal">
                    <Storyboard>
                        <ColorAnimation To="LightGray" 
                                Storyboard.TargetProperty="(Path.Stroke).(SolidColorBrush.Color)" 
                                Duration="0:0:0.8"
                                FillBehavior="Stop"
                                Storyboard.TargetName="OuterRing"/>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <Path Fill="Transparent"
              StrokeThickness="{TemplateBinding Thickness}"
              Stroke="{TemplateBinding Outline}"
              StrokeDashCap="Flat"
              x:Name="OuterRing">
            <Path.Data>
                <PathGeometry>
                    <PathGeometry.Figures>
                        <PathFigureCollection>
                            <PathFigure x:Name="OutlineFigurePart">
                                <PathFigure.Segments>
                                    <PathSegmentCollection>
                                        <ArcSegment x:Name="OutlineArcPart" IsLargeArc="True" SweepDirection="Clockwise"/>
                                    </PathSegmentCollection>
                                </PathFigure.Segments>
                            </PathFigure>
                        </PathFigureCollection>
                    </PathGeometry.Figures>
                </PathGeometry>
            </Path.Data>
        </Path>
    </Grid>
</ControlTemplate>

IsValueOutOfRange更改时,它将控制切换到不同的状态,从而运行不同的动画。

这只是一个示例,我使用设备上的按钮来切换控件的状态,它可以正常工作。但是,如果要适应项目,则需要满足以下两个条件:

  1. 提供初始Stroke
  2. 第一次加载控件时,默认IsValueOutOfRangeFalse,因此Path的默认颜色应与Normal状态相同。
© www.soinside.com 2019 - 2024. All rights reserved.