第二十三章:觸發器和行爲(十)

響應水龍頭
切換視圖的各種表現形式演示了一種響應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>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章