How do I pass the Button as CommandParameter from XAML in a Xamarin.Forms Page?
Asked Answered
L

4

24

I would like to pass a Xamarin.Forms.Button in it's own Command as the CommandParameter to my ViewModel. I know how to achieve this from the code behind e.g. ...

XAML (with most properties missed out for brevity)

<Button x:Name="myButton"
    Text="My Button"
    Command="{Binding ButtonClickCommand}"/>

XAML.cs

public partial class MyTestPage
{
    public MyTestPage()
    {
        InitializeComponent();

        myButton.CommandParameter = myButton;
    }
}

ViewModel

public class MyViewModel : ViewModelBase
{
    public MyViewModel()
    {
        ButtonClickCommand = new Command(
            (parameter) =>
            {
                var view = parameter as Xamarin.Forms.Button;
                if (view != null)
                {
                    // Do Stuff
                }
            });
    }

    public ICommand ButtonClickCommand { get; private set; }
}

... BUT is it possible to declare the CommandParameter in the XAML itself? Or in other words what is the binding syntax to set the parameter to the button itself?

<Button x:Name="myButton"
        Text="My Button"
        Command="{Binding ButtonClickCommand}"
        CommandParameter="{[WHAT WOULD GO HERE]}"/>

btw I've already tried CommandParameter="{Binding RelativeSource={RelativeSource Self}}" and that didn't work.

Thanks,

Lipp answered 18/9, 2014 at 12:1 Comment(4)
Why do you need the button in your VM?Hueyhuff
Hi @AlexAnderson. Yeah I'm not super keen about it either. We are introducing Xamarin.Forms into an existing Xamarin iOS project. Just experimenting with ways to get a native UIPopoverController to show from a Xamarin.Form Page. There is no Forms support for Popups so just looking at ways around it at the moment and one of the hurdles is I need to know which UIElement to show the popup from ... hence passing the button. As I said ... kinda feels hokey. I'll go try your suggestion below. ThanksLipp
As for popups check out the implementation of ContentPage.DisplayActionSheet(...) - if the action sheet is not enough you can reverse-engineer the code that shows it. And getting the Button reference will still require finding the UIButton reference from that. You are going to be better off with a custom rendererOrnithischian
Hi @StenPetrov. The issue with creating a custom renderer for the popup is that the UIPopoverController is an NSObject and not a UIView object.Lipp
S
33

Xamarin.Forms has a Reference markup extension that does just that:

<Button x:Name="myButton"
    Text="My Button"
    Command="{Binding ButtonClickCommand}"
    CommandParameter="{x:Reference myButton}"/>

Although, this is the first time I'm seeing this need, and you probably can better separate your Views from your ViewModels and solve this by using a cleaner pattern, or by not sharing a command across buttons.

Shuster answered 18/9, 2014 at 14:5 Comment(9)
Hi @StephaneDelcroix. Unfortunately that didn't work either .. "Exception has been thrown by the target of an invocation."Lipp
could you share a stack trace ? are you using the xaml 2009 xmlns ? are you using the latest (1.2.2 or 1.2.3-pre2) version of XF ?Shuster
I'm sorry @GavinSutherland, but I just tested this on 1.2.3-pre-2 and it works as expected.Shuster
Hi @StephaneDelcroix. I'll check the namespace and xf versions. If they are up to date then I'll perhaps try it in an empty project. Thanks for the updateLipp
Hi @StephaneDelcroix. I'm using v1.2.2 and I've got the following namespaces declared: xmlns="http://xamarin.com/schemas/2014/forms" and xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml". Does this look correct?Lipp
@GavinSutherland: yes, that's all right. I haven't tried with 1.2.2.Shuster
What would this look like in C#? And how would I refer to the button inside the command itself?Gambell
When I try that in code, I get an error "Specified cast is not valid", directly related to the CommandParameterProperty line.Gambell
This is exactly what I was looking for, thank you. Although it somewhat destroys the separation of user interface and code, I could not come up with a better solution to my problem: I want to be able to switch between input fields (Xamarin.Forms.Entry) after the user presses the 'Return' key using this solution: https://mcmap.net/q/447004/-change-return-to-be-next-done-key-in-xamarin-forms-shared-project @jbyrd: This is how my ViewModel's code looks like: this.FocusVisualElementCommand = new Command<VisualElement>(visualElement => visualElement?.Focus());Stclair
P
8
 <Button x:Name="myButton"
        Text="My Button"
        Command="{Binding ButtonClickCommand}"
        CommandParameter="{x:Reference myButton}"/>

In your ViewModel

public YourViewModel()
{
    ButtonClickCommand= new Command(ButtonClicked);
}

private async void ButtonClicked(object sender)
{
    var view = sender as Xamarin.Forms.Button;
}
Pole answered 10/5, 2018 at 18:28 Comment(2)
Not working with Prism, asking param in while passing in command.Osteomyelitis
Thanks! This really helped me.Spunk
D
3

A simple method would be:

In XAML:

 <Button Text="BUTTON-TEST"
            Clicked="Avaliar"
            CommandParameter="like"/>

In C#:

private void Avaliar(object sender, EventArgs e)
{
     Console.WriteLine(((Button)sender).CommandParameter);
}
Deckert answered 22/4, 2020 at 12:32 Comment(1)
Doesn't follow MVVM which I'm guessing is why the OP is using a VM.Bobette
H
0
<Button x:Name="myButton"
    Text="My Button"
    Command="{Binding ButtonClickCommand}"
    CommandParameter={Binding RelativeSource=
                               {RelativeSource
                                Mode=FindAncestor,
                                AncestorType={x:Type Button}}/>

Should work, but im still at a loss why you need the button? The point of MVVM is to seperate Data and UI. everything you should need todo to the button can be done via DataBindings.

If the above doesnt work, the only other thing to try is to give the button an x:Key and CommandParamter = {StaticResource 'x:Key'}

Hueyhuff answered 18/9, 2014 at 12:27 Comment(3)
Xamarin.Forms bindings do not have any RelativeSource property, nor a RelativeSource markup extension.Shuster
Hi @AlexAnderson ... yeah neither of those suggestions worked I'm afraid.Lipp
@Alex What if you want to change the VisualState of Caller button, I think then we need to do that.Peddada

© 2022 - 2024 — McMap. All rights reserved.