Hands-On Mobile Development with .NET Core
上QQ阅读APP看书,第一时间看更新

Triggers

Triggers can be defined as declarative actions that need to be executed. The different types of triggers are as follows:

  • Property trigger: Property changes for a view 
  • Data trigger: Data value changes for a binding 
  • Event trigger: The occurrence of certain events on the target view
  • Multi-trigger: Using this, it's also possible to implement a combination of triggers

To illustrate the use of triggers, we can use our previous example, where ReleaseDate for a certain item does not exist. In this scenario, because of TargetNullValue attribute being defined, the text of the label would be set to Release Unknown. Here, we can make use of a property trigger, which set the font color:

<Label x:Name="ReleaseDate" Text="{Binding ReleaseDate, StringFormat='Release {0:M/d/yyyy}', TargetNullValue='Release Unknown'}">
<Label.Triggers>
<Trigger TargetType="Label" Property="Text" Value="Release
Unknown
">

<Setter Property="TextColor" Value="Red" />
</Trigger>
</Label.Triggers>
</Label>

Here, the target type defines the containing element (that is, the target of the trigger action), and the property and value define the cause of the trigger. Multiple setters then can be applied to the target modifying the values of the view.

In a similar fashion, we could have created a data trigger to set the color of the title depending on the release date label's value:

<Label Text="{Binding Title, Mode=OneTime}" FontSize="Large">
<Label.Triggers>
<DataTrigger TargetType="Label"
Binding="{Binding Source={x:Reference ReleaseDate},
Path=Text}"
Value="Release Unknown">
<Setter Property="TextColor" Value="Red" />
</DataTrigger>
</Label.Triggers>
</Label>

Here, we are setting the binding context of the DataTrigger to another view (that is, View-to-View) binding. If we were using the view model as the binding context, we could have used the ReleaseDate as well.

Finally, if we have don't have a release date but we have the data to support that an item is, in fact, already released to the public, we can use MultiTrigger:

<MultiTrigger TargetType="Label">
<MultiTrigger.Conditions>
<PropertyCondition Property="Text" Value="Release Unknown" />
<BindingCondition Binding="{Binding IsReleased}" Value="false"/>
</MultiTrigger.Conditions>
<Setter Property="TextColor" Value="Red" />
</MultiTrigger>

Event triggers are odd members of the trigger family, since they rely on events being triggered on the target view instead of Setters; they use the so-called Action.

For instance, in order add a little UX enhancement, we can add a fade animation to the image in the item view. In order to use this animation, we first need to implement it as part of an Action:

 public class AppearingAction : TriggerAction<VisualElement>
{
public AppearingAction() { }

public int StartsFrom { set; get; }

protected override void Invoke(VisualElement visual)
{
visual.Animate("FadeIn",
new Animation((opacity) => visual.Opacity = opacity, 0, 1),
length: 1000, // milliseconds
easing: Easing.Linear);
}
}

After TriggerAction is created, we can now define an event trigger on the image (that is, using the BindingContextChanged event):

<Image Source="{Binding Image}" HorizontalOptions="FillAndExpand">
<Image.Triggers>
<EventTrigger Event="BindingContextChanged">
<actions:AppearingAction />
</EventTrigger>
</Image.Triggers>
</Image>

This will create a subtle fade-in effect, which should coincide with the loading of the image, hence a more pleasant user experience.

Actions can also be used with property and data triggers using EnterAction and ExitAction, defining the two states according to the trigger condition(s). However, in the context of property and data triggers, in order to create more generalized states, as well as modifying the common states for a control, Visual State Manager (VSM) can also be utilized. This way, multiple setters can be unified in a single state, decreasing the clutter within the XAML tree, creating a more maintainable structure.