Search code examples
xamarinbuttoncommandmvvmcross

Xamarin Forms MvvmCross binding a button command error


I'm working on a Xamarin Forms MvvmCross project. I'm binding a common button command on the view with a IMvxAsyncCommand on the view model, as follows:

  • View

     <views:MvxContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                       xmlns:views="clr- namespace:MvvmCross.Forms.Views;assembly=MvvmCross.Forms"
                       x:Class="TestProject.Pages.TestPage">
     <ContentView>
         <StackLayout>
             <Button Text="Test the command!" Command="{Binding TestAsyncCommand}"/>
         </StackLayout>
     </ContentView>
    

    </views:MvxContentPage>

  • View model

     namespace TestProject.ViewModels
     {
         public class TestViewModel : MvxNavigationViewModel
         {
             public TestViewModel(IMvxLogProvider logProvider, IMvxNavigationService navigationService)
                 : base(logProvider, navigation)
             {
             }
    
             public IMvxAsyncCommand TestAsyncCommand => new MvxAsyncCommand(async () => await TestAsyncCommandMethod());
    
             private async Task TestAsyncCommandMethod()
             {
                 //await some stuff
             }
         }
     }
    

Anythings seems to work fine but rarely sometimes after a pression of the button it becames disable. What could happen? It does not happen if I use Command in place of MvxAsyncCommand, like here:

public Command TestAsyncCommand => new Command(async () => await TestAsyncCommandMethod());

Note: TestAsyncCommandMethod is entirely encased in a try-catch block to avoid possible exceptions.


Solution

  • I think what you are doing wrong here is that instead of creating a Property to Bind the View and the ViewModel you are using a field can you try this:

    public IMvxAsyncCommand TestAsyncCommand {get; set;}
    

    And then in your constructor do this:

    public TestViewModel(IMvxLogProvider logProvider, IMvxNavigationService navigationService)
            : base(logProvider, navigation)
        {
          TestAsyncCommand = new MvxAsyncCommand(async () => await TestAsyncCommandMethod());
        }
    

    UPDATE

    This seems to be a bug with MvvmCross! Issue can be found in the added link

    https://github.com/MvvmCross/MvvmCross/issues/1589