UWP equivalent for WPF Style.Triggers



我创建了一个在 WPF 中工作的控件,现在尝试移植到 UWP。

该控件公开一个布尔属性,当设置为 true 时,我通过重复行为为"永远"的故事板更改路径(笔触(的背景颜色。

在阅读了大量文章后,我了解到UWP使用VisualState,交互性等,但没有触发器。我尝试重新设计代码,但没有让背景更改/动画。

WPF 中控件模板的一部分

<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. ViewModel 中的 ValueOutOfRange设置为"True"时,Path.Stroke 颜色应在"OuterRing"上以动画形式显示
  2. ViewModel 中的 ValueOutOfRange设置为"False"时,Path.Stroke 颜色应恢复正常。

UWP 中控件模板的一部分

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

在 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状态相同。

最新更新