Quantcast
Channel: xaml – Tag
Viewing all articles
Browse latest Browse all 3

Attached property for TapGestureRecognizer

$
0
0

While creating Xamarin.Forms applications, definitely you are going to need TapGestureRecognizer often. Implementing it in XAML many times may end up with a lot of unnecessary code. Let’s take a look at that simple clickable Image:

<Image Source="img.png">
  <Image.GestureRecognizers>
    <TapGestureRecognizer Command="{Binding CloseCommand}" CommandParamter="{Binding .}" />
  </Image.GestureRecognizers>
</Image>

This is a lot of lines, especially when you have to add many clickable controls. However, we can do it better and put everything into a single line using our custom attached property:

xmlns:ex="clr-namespace:MyApp.Extensions;assembly=MyApp"
...
<Image Source="img.png" ex:Gestures.TapCommand="{ex:Command CloseCommand, Parameter={Binding .}}"/>

Implementation

using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using System.Windows.Input;

namespace MyApp.Extensions
{
    [ContentProperty("Command")]
    public class CommandExtension : BindableObject, IMarkupExtension
    {
        public string Command { get; set; }

        // Binding source for Command
        public object Source { get; set; }

        // CommandParameter
        public object Parameter { get; set; }

        public object ProvideValue(IServiceProvider serviceProvider)
        {
            return this;
        }
    }
}

using Xamarin.Forms;
using System.Linq;

namespace MyApp.Extensions
{
    public class Gestures
    {
        #region TapCommand

        public static readonly BindableProperty TapCommandProperty = 
            BindableProperty.CreateAttached<Gestures, CommandExtension>(
              x => (CommandExtension)x.GetValue(Gestures.TapCommandProperty), 
              null, BindingMode.OneWay, propertyChanged: TapCommandChanged);

        #endregion

        private static void TapCommandChanged(BindableObject source, CommandExtension oldVal, 
                                              CommandExtension newVal)
        {
            var tapGesture = new TapGestureRecognizer();
            
            // Set command
            var commandBinding = new Binding(newVal.Command, source: newVal.Source);
            tapGesture.SetBinding(TapGestureRecognizer.CommandProperty, commandBinding);
            
            // Set command parameter
            if (newVal.Parameter is Binding)
            {
                tapGesture.SetBinding(TapGestureRecognizer.CommandParameterProperty, 
                                      newVal.Parameter as Binding);
            }
            else
            {
                tapGesture.CommandParameter = newVal.Parameter;
            }
            
            // Remove old TapGestureRecognizer
            var view = source as View;
            var toRemove = view.GestureRecognizers.OfType<TapGestureRecognizer>().FirstOrDefault();
            view.GestureRecognizers.Remove(toRemove);

            // Add new one
            view.GestureRecognizers.Add(tapGesture);
        }
    }
}


Viewing all articles
Browse latest Browse all 3

Trending Articles