Home > Software design >  Xamarin Forms: How to send object and event through to ViewModel on ImageButton Clicked using Comman
Xamarin Forms: How to send object and event through to ViewModel on ImageButton Clicked using Comman

Time:12-16

I've created a CustomElementTagger class which allows me to set and get custom set tags on view elements. I need this because I want to have a single command that gets executed but has different behavior on the corresponding tag on the element. In the ViewModel I want to receive the tag and work with it accordingly but the Command never executes. I've also tried it as an Object but the object never comes back as I need it and when I try to cast the Object to the ImageButton I get an error that I cannot cast this Object.

I've looked up youtube videos by JamesMontemagno but everything I look at that is using EventToCommandBehaviour are ListViews with EventName = "ItemSelected".

Also viewed a number of articles and neither of those helped me to understand how to make this work.

All I want is to get my ImageButton sender.
Many Thanks in advance.

CustomElementTagger: Class

public class CustomElementTagger
{
    public static readonly BindableProperty TagProperty = BindableProperty.Create("Tag", typeof(object), typeof(CustomElementTagger), null);

    public static string GetTag(BindableObject bindable)
    {
        return (string)bindable.GetValue(TagProperty);
    }

    public static void SetTag(BindableObject bindable, string value)
    {
        bindable.SetValue(TagProperty, value);
    }
}

XAML

<ImageButton WidthRequest="200"
                HeightRequest="200"
                HorizontalOptions="CenterAndExpand"
                VerticalOptions="EndAndExpand"
                BackgroundColor="Red"
                tagger:CustomElementTagger.Tag="1">
    <ImageButton.Behaviors>
        <xct:EventToCommandBehavior EventName="Clicked"
                                    Command="{Binding KeyboardTapCommand}" />
    </ImageButton.Behaviors>
</ImageButton>

ViewModel

public class SpellViewModel: BaseViewModel
{
    public ICommand NextPageCommand { get; private set; }
    public ICommand PreviousPageCommand { get; private set; }
    public ICommand KeyboardTapCommand { get; private set; }

    public SpellViewModel()
    {
        Initialize();
    }

    void Initialize()
    {
        InitializeCommands();
    }

    void InitializeCommands()
    {
        NextPageCommand = Navigation.NextPage(nameof(CopyWhatIDoPage));
        PreviousPageCommand = Navigation.PreviousPage();
        KeyboardTapCommand = new Command<ImageButton>(ReadVirtualKeyboardTap);
    }

    void ReadVirtualKeyboardTap(ImageButton btn) //This never gets executed...
    {
        var tag = CustomElementTagger.GetTag(btn);
    }
}

CodePudding user response:

I don't know how EventToCommandBehavior works under the hood. But I argue your approach here, is against MVVM. Generally, the view models should be unaware of the details of the view. Here the ImageButton is a UI element hence a view detail, which your view model should not care about. You can use CommandParameter to achieve what you want. Usually, using command parameters, you can have a single general command that can act differently based on the parameter which in your case is the tag you are assigning.

View:

<ImageButton WidthRequest="200"
                HeightRequest="200"
                HorizontalOptions="CenterAndExpand"
                VerticalOptions="EndAndExpand"
                BackgroundColor="Red"
                CommandParameter="1"
                Command="{Binding KeyboardTapCommand}" />

View Model:

KeyboardTapCommand = new Command<string>(ReadVirtualKeyboardTap);


void ReadVirtualKeyboardTap(string tag)
{   
}

This way, the tag (as a command parameter) will be directly sent to your ReadVirtualKeyboardTap method. And you can decide what to do based on that.

  • Related