響應水龍頭
切換視圖的各種表現形式演示了一種響應XAML文件中的點擊的方法。 如果將tap事件集成到VisualElement類中,您可以使用EventTrigger更直接且更輕鬆地獲取它們。 但是您無法將EventTrigger附加到TapGestureRecognizer。
解決這個小限制是一種專門用於點擊的行爲的目的。 這叫做TapBehavior:
namespace Xamarin.FormsBook.Toolkit
{
public class TapBehavior : Behavior<View>
{
TapGestureRecognizer tapGesture;
static readonly BindablePropertyKey IsTriggeredKey =
BindableProperty.CreateReadOnly("IsTriggered", typeof(bool),
typeof(TapBehavior), false);
public static readonly BindableProperty IsTriggeredProperty =
IsTriggeredKey.BindableProperty;
public bool IsTriggered
{
private set { SetValue(IsTriggeredKey, value); }
get { return (bool)GetValue(IsTriggeredProperty); }
}
protected override void OnAttachedTo(View view)
{
base.OnAttachedTo(view);
tapGesture = new TapGestureRecognizer();
tapGesture.Tapped += OnTapped;
view.GestureRecognizers.Add(tapGesture);
}
protected override void OnDetachingFrom(View view)
{
base.OnDetachingFrom(view);
view.GestureRecognizers.Remove(tapGesture);
tapGesture.Tapped -= OnTapped;
}
async void OnTapped(object sender, EventArgs args)
{
IsTriggered = true;
await Task.Delay(100);
IsTriggered = false;
}
}
}
TapBehavior類定義了一個名爲IsTriggered的布爾屬性,但它的功能與普通屬性完全不同。首先,它由只讀可綁定屬性支持。這意味着
IsTriggered屬性只能在TapBehavior類中設置,並且當IsTriggered屬性在十分之一秒內變爲true時,類設置IsTriggered的唯一時間是TapGestureRecognizer的事件處理程序。
換句話說,Tapped事件被轉換爲屬性值的非常短暫的峯值 - 這讓人想起事件是如何在數字硬件中觸發的。但IsTriggered屬性可以
然後在DataTrigger中引用。
假設您喜歡ShiverButton的想法,但是您希望將概念應用於除Button之外的其他內容,這意味着您需要響應Tapped事件。您可以使用EventTrigger,但TapBehavior允許您使用DataTrigger。
爲了演示,這裏是BoxViewTapShiver,它將TapBehavior對象附加到三個Box View元素,每個元素還包括一個DataTrigger,它引用行爲並在其EnterActions集合中調用ShiverAction:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:toolkit=
"clr-namespace:Xamarin.FormsBook.Toolkit;assembly=Xamarin.FormsBook.Toolkit"
x:Class="BoxViewTapShiver.BoxViewTapShiverPage">
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="BoxView">
<Setter Property="WidthRequest" Value="200" />
<Setter Property="HeightRequest" Value="50" />
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout>
<BoxView Color="Red">
<BoxView.Behaviors>
<toolkit:TapBehavior x:Name="tapBehavior1" />
</BoxView.Behaviors>
<BoxView.Triggers>
<DataTrigger TargetType="BoxView"
Binding="{Binding Source={x:Reference tapBehavior1},
Path=IsTriggered}"
Value="True">
<DataTrigger.EnterActions>
<toolkit:ShiverAction />
</DataTrigger.EnterActions>
</DataTrigger>
</BoxView.Triggers>
</BoxView>
<BoxView Color="Green">
<BoxView.Behaviors>
<toolkit:TapBehavior x:Name="tapBehavior2" />
</BoxView.Behaviors>
<BoxView.Triggers>
<DataTrigger TargetType="BoxView"
Binding="{Binding Source={x:Reference tapBehavior2},
Path=IsTriggered}"
Value="True">
<DataTrigger.EnterActions>
<toolkit:ShiverAction />
</DataTrigger.EnterActions>
</DataTrigger>
</BoxView.Triggers>
</BoxView>
<BoxView Color="Blue">
<BoxView.Behaviors>
<toolkit:TapBehavior x:Name="tapBehavior3" />
</BoxView.Behaviors>
<BoxView.Triggers>
<DataTrigger TargetType="BoxView"
Binding="{Binding Source={x:Reference tapBehavior3},
Path=IsTriggered}"
Value="True">
<DataTrigger.EnterActions>
<toolkit:ShiverAction />
</DataTrigger.EnterActions>
</DataTrigger>
</BoxView.Triggers>
</BoxView>
</StackLayout>
</ContentPage>
三個TapBehavior對象中的每一個都具有唯一的名稱,該名稱由相應的DataTrigger引用。 當您點擊BoxView時,它會顫抖,並且它們都可以獨立工作。
將TapBehavior和DataTrigger對象放在樣式中以減少重複標記是非常誘人的,但這不起作用。 這將導致在三個BoxView元素之間共享一個TapBehavior。 此外,每個DataTrigger按名稱引用相應的TapBehavior。
如果你想在這種情況下減少標記,你將再次需要定義一個新類。 ShiverViews程序演示了這一點。 它首先定義一個名爲ShiverView的類,它派生自BoxView並添加TapBehavior和DataTrigger:
<BoxView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:toolkit=
"clr-namespace:Xamarin.FormsBook.Toolkit;assembly=Xamarin.FormsBook.Toolkit"
x:Class="ShiverViews.ShiverView">
<BoxView.Behaviors>
<toolkit:TapBehavior x:Name="tapBehavior" />
</BoxView.Behaviors>
<BoxView.Triggers>
<DataTrigger TargetType="BoxView"
Binding="{Binding Source={x:Reference tapBehavior},
Path=IsTriggered}"
Value="True">
<DataTrigger.EnterActions>
<toolkit:ShiverAction />
</DataTrigger.EnterActions>
</DataTrigger>
</BoxView.Triggers>
</BoxView>
與SwitchClone類一樣,您也可以在代碼隱藏文件中添加一些屬性,並在XAML文件中引用它們。
然後,ShiverViewsPage XAML文件可以使用隱式樣式實例化三個獨立的ShiverView對象:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:ShiverViews"
x:Class="ShiverViews.ShiverViewsPage">
<StackLayout>
<StackLayout.Resources>
<ResourceDictionary>
<Style TargetType="local:ShiverView">
<Setter Property="WidthRequest" Value="200" />
<Setter Property="HeightRequest" Value="50" />
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
</Style>
</ResourceDictionary>
</StackLayout.Resources>
<local:ShiverView Color="Red" />
<local:ShiverView Color="Green" />
<local:ShiverView Color="Blue" />
</StackLayout>
</ContentPage>