简体   繁体   中英

Button command binding doesn't work in Xamarin.Forms

I'd like to bind a command to the command property of my button. This seemed pretty straightforward since I've done this many times before in WPF and the method here is very similar. Let me show some code snippets.

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" 
         x:Class="MyApp.View.CustomPage"
         Title="Something">

<ContentPage.Content>
    <StackLayout>
        <Button x:Name="numBtn" Text="Increase number" Command="{Binding IncreaseCommand}" />
        <Label x:Name="numLabel" Text="{Binding numberText}" />
    </StackLayout>
</ContentPage.Content>
</ContentPage>

Code-behind

public partial class CustomPage : ContentPage
{   
    public CustomPage ()
    {
        InitializeComponent ();
        BindingContext = ViewModelLocator.ViewModel();  //ViewModelLocator is singleton, gives
                                                        //you a ViewModel instance
    }
}

ViewModel

public ICommand IncreaseCommand { get; private set; }
private int number;
public string numberText { get; private set;}

the constructor:

public ViewModel()
{
    IncreaseCommand = new Command (() => IncreaseExecuted ());
    number = 0;
    numberText = number.ToString ();
    OnPropertyChanged (numberText);
}

and then

private void IncreaseExecuted()
{
    number++;
    numberText = number.ToString ();
    OnPropertyChanged (numberText);
}

When I run the app using the Xamarin Android Player (KitKat) I see the button, and the label reading 0. Then I press the button and nothing happens. I tried checking what happens with breakpoints but the app doesn't pause, not even when they're in the constructor of my ViewModel. I guess it's something to do with the emulator. Anyway, I think the binding is ok since I can see a "0" on the screen. What could be the problem? Let me show my ViewModelBase class just in case:

ViewModelBase

public abstract class ViewModelBase : INotifyPropertyChanged
{

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(String propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Maybe my numberText property doesn't get updated when I call OnPropertyChanged ? But I've used the exact same ViewModelBase class several times before and it always worked fine. One last thing, my CustomPage page is wrapped inside a NavigationPage which is a child of a TabbedPage :

MainPage.xaml.cs

this.Children.Add (new NavigationPage (new CustomPage ()) {Title="Something"} );

This shouldn't affect anything but there it is just in case. So what's wrong with my command binding? Thank you in advance!

You are almost there. Take a close look at your call to the OnPropertyChanged method; you are passing the value of numberText and not the name. If you change your code to pass "numberText" I expect it shall work properly.

Edit: I should add that the the OnPropertyChanged call in the constructor has the same problem. The reason you see "0" at startup is that the view is simply using the existing binding to retrieve the value.

Edit 2: Now that Xamarin supports C# 6.0, you can use the new "nameof" expression that eliminates the need for a hard-coded string. Alternately, you can use MvvmCross, MvvmLight, or XLabs' MVVM classes.

This answer is not directly related to the problem of the original question, however this question is the one that ranks highest in search engines and the title of this question is ambiguous to the question that this answer answers.

I was having issues with a Command that wouldn't fire the associated command action. My problem was that I had defined the Command as a field instead of a property .

Works:

public Command MyCommand { get; set; }

Doesn't work:

public Command MyCommand;

Hope this helps someone else.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM