how to use commandparamter to pass the coordinates of the tap event while using mvvm

晓明 于 20 Reputation points
2024-01-25T15:24:55.8366667+00:00

When an image is clicked, I want to get the click coordinates of the image. This is easy to accomplish if i employ an event mechanism. But what property should commandparameter bind to from TapGestureRecognizer when i use MVVM?

.NET MAUI
.NET MAUI
A Microsoft open-source framework for building native device applications spanning mobile, tablet, and desktop.
3,900 questions
0 comments No comments
{count} votes

Accepted answer
  1. Leon Lu (Shanghai Wicresoft Co,.Ltd.) 79,471 Reputation points Microsoft Vendor
    2024-01-26T02:37:19.8466667+00:00

    Hello,

    You can do this by creating a custom behavior or an attached property that captures the tap event and then passes the coordinates to the command. Firstly, Create a custom behavior: - Define a behavior that attaches to the TapGestureRecognizer event. - In the event handler, get the tap coordinates. - Invoke the command with the coordinates as the parameter.

    public class TapCoordinateBehavior : Behavior<Image> {
        
        public static readonly BindableProperty CommandProperty =
            BindableProperty.Create(nameof(Command), typeof(ICommand), typeof(TapCoordinateBehavior), null);
    
    
       public ICommand Command
        {
            get { return (ICommand)GetValue(CommandProperty); }
            set { SetValue(CommandProperty, value); }
        }
       public Image bindable { get; private set; }
    
       protected override void OnAttachedTo(Image bindable) {
            base.OnAttachedTo(bindable);
            this.bindable = bindable;
            bindable.BindingContextChanged += OnBindingContextChanged;
            var tapGestureRecognizer = new TapGestureRecognizer();
            tapGestureRecognizer.Tapped += OnTapped;
            bindable.GestureRecognizers.Add(tapGestureRecognizer);
        }
        protected override void OnDetachingFrom(Image bindable) {
            base.OnDetachingFrom(bindable);
            bindable.BindingContextChanged -= OnBindingContextChanged;
            if (bindable.GestureRecognizers.FirstOrDefault() is TapGestureRecognizer tapGestureRecognizer) {
                tapGestureRecognizer.Tapped -= OnTapped;
            
            }
            bindable = null;
        }
    
       protected override void OnBindingContextChanged()
        {
            base.OnBindingContextChanged();
            BindingContext = bindable.BindingContext;
        }
    
       void OnBindingContextChanged(object sender, EventArgs e)
        {
            OnBindingContextChanged();
        }
    
       private void OnTapped(object sender, EventArgs e) {
            if (sender is Image view && e is TappedEventArgs tappedEventArgs) {
                var point = new Point(tappedEventArgs.GetPosition(bindable).Value.X, tappedEventArgs.GetPosition(bindable).Value.Y);
                if (Command != null && Command.CanExecute(point)) {
                    Command.Execute(point);
                }
            }
        }
    }
    

    then open your layout XAML, you would attach this behavior to your image and bind the Command to your ViewModel.

    <ContentPage 
    ...
                 x:Class="MauiSendEmail.NewPage1"
                 xmlns:local="clr-namespace:MauiSendEmail"
                >
    
    <Image Source="dotnet_bot.png" BackgroundColor="Red">
            <Image.Behaviors>
                <local:TapCoordinateBehavior Command="{Binding TapCommand}" />
            </Image.Behaviors>
        </Image>
    
    </ContentPage>
    

    In your viewModel, you can get the Coordinate in the Command.

    public class YourViewModel
    {
        public ICommand TapCommand { get; }
        public YourViewModel()
        {
            InitializeComponent();
            TapCommand = new Command((obj) =>
            {
                if(obj != null) {
                    Point Coordinate = (Point)obj ;
                    var X= Coordinate.X;
                    var Y= Coordinate.Y;
                }          
            });
          
        }
    

    Best Regards, Leon Lu


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment". Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.