Xamarin.Forms のコントロールは Tapped イベントすら持ってないので、Trigger でインタラクションを記述することがまだ難しいです;
なので Tapped のジェスチャに反応する機能を拡張する GestureRecognizer を利用してコントロールを作ってみたいと思います
普通に GestureRecognizer を利用する場合、コードビハインドでイベントハンドラを追加したり、ViewModel の Command をデータバインドするみたいです
ただ、コントロールとして使いまわす場合 XAML だけで完結するような記述ができると非常にラクなので、できればそうしたいところ・・・
今回の修正は下記の網掛け部分
まずは GestureRecognizerBehavior というビヘイビアを作ります
/// <summary> /// GestureRecognizer に反応する Behavior /// </summary> public class GestureRecognizeBehavior : Behavior<View> { /// <summary> /// アタッチされた View /// </summary> private View bindable = null; /// <summary> /// アタッチされた GestureRecognizer の BindableProperty /// </summary> public static readonly BindableProperty GestureRecognizerProperty = BindableProperty.Create<GestureRecognizeBehavior, TapGestureRecognizer>(p => p.GestureRecognizer, null); /// <summary> /// アタッチされた GestureRecognizer /// </summary> public TapGestureRecognizer GestureRecognizer { get { return (TapGestureRecognizer)this.GetValue(GestureRecognizerProperty); } set { this.SetValue(GestureRecognizerProperty, value); } } /// <summary> /// Behavior がアタッチされた時の処理 /// </summary> /// <param name="bindable">アタッチされた View</param> protected override void OnAttachedTo(View bindable) { base.OnAttachedTo(bindable); this.bindable = bindable; if (this.bindable == null || this.GestureRecognizer == null) { return; } this.GestureRecognizer.Tapped += this.OnGestured; this.bindable.GestureRecognizers.Add(this.GestureRecognizer); } /// <summary> /// GestureRecognizer のイベントハンドラ /// </summary> /// <param name="sender">イベント発行者</param> /// <param name="args">イベント引数</param> private void OnGestured(object sender, EventArgs args) { // 背景色を反転 this.bindable.BackgroundColor = Color.FromRgba( 1.0d - this.bindable.BackgroundColor.R, 1.0d - this.bindable.BackgroundColor.G, 1.0d - this.bindable.BackgroundColor.B, this.bindable.BackgroundColor.A); } /// <summary> /// Behavior がデタッチされた時の処理 /// </summary> /// <param name="bindable"></param> protected override void OnDetachingFrom(View bindable) { if (this.bindable != null && this.GestureRecognizer != null) { this.bindable.GestureRecognizers.Remove(this.GestureRecognizer); this.GestureRecognizer.Tapped -= this.OnGestured; this.GestureRecognizer = null; this.bindable = null; } base.OnDetachingFrom(bindable); } }
View がアタッチされたら BindableProperty に設定されている GestureRecognizer を View に追加してイベントを監視するようにしています
処理の内容は Tapped ジェスチャに反応して BackgroundColor を反転しているだけ
汎用的に作ろうと思ったらなぜか Interface にも 基底クラスの GestureRecognizer にも Command やイベントの定義がなく使えませんでした; どちらにせよ GestureRecognizer が TapGestureRecognizer しかないので、これに限定した実装にしてしまいました・・・今後整備されそうだけども
お次に XAML
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:b="clr-namespace:XamarinControl.Behaviors;assembly=XamarinControl" x:Class="XamarinControl.Views.TopPage"> <BoxView BackgroundColor="#FFFF8469" WidthRequest="200" HeightRequest="200" HorizontalOptions="Center" VerticalOptions="Center"> <BoxView.Behaviors> <b:GestureRecognizeBehavior> <b:GestureRecognizeBehavior.GestureRecognizer> <TapGestureRecognizer NumberOfTapsRequired="1" /> </b:GestureRecognizeBehavior.GestureRecognizer> </b:GestureRecognizeBehavior> </BoxView.Behaviors> </BoxView> </ContentPage>
Behavior と GestureRecognizer を記述・・・コードビハインドも ViewModel も使ってませんね
とりあえず実行
タップしたら色が交互に切り替わるようになりました!