Home > Mobile >  Xamarin.Android Keeps Stopping
Xamarin.Android Keeps Stopping

Time:02-15

I am new both to MVVM pattern and Xamarin platform. Im trying to crate a bindable interface by using a view model. I started with a very simple task: Take the Entry input from the user, and send it to the label text after clicking the button.

ViewModel ---> Commands ---> EntryCommand.cs

namespace HelloWorld.ViewModel.Commands
{
    public class EntryCommand : ICommand
    {
        public ViewModel VM { get; set; }
        public EntryCommand( ViewModel vm)
        {
            VM = vm;
        }

        public event EventHandler CanExecuteChanged;

        public bool CanExecute(object parameter)
        {
            return true;
        }
        
        public void Execute(object parameter)
        {
            VM.ChangeLabelText();
        }
    }
}

ViewModel.cs

namespace HelloWorld.ViewModel
{
    public class ViewModel: INotifyPropertyChanged
    {  
        public EntryCommand EntryCommand { get; set; }
        public event PropertyChangedEventHandler PropertyChanged;

        public ViewModel()
        {
            EntryCommand = new EntryCommand(this);
        }

        private void OnPropertyChanged(string PropertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
        }

        public string LabelText { get; set; }
        public string Name 
        {
            get { return Name; }
            set 
            {
                Name = value;
                OnPropertyChanged("Name");
            }
        }
        public void ChangeLabelText()
        {
            if(Name!=null)
            {
                LabelText = Name;
            }
        }

    }
}

Bindable Xaml file:

MainPage.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="HelloWorld.MainPage"
             xmlns:ViewModel="clr-namespace:HelloWorld.ViewModel" x:DataType="ViewModel:ViewModel">

    <ContentPage.Resources>
        <ViewModel:ViewModel x:Key="vm"/>
    </ContentPage.Resources>

    <StackLayout BindingContext="{StaticResource vm}" BackgroundColor="AliceBlue"
                 Margin="15">

        <Label Text="{Binding Name, Mode=TwoWay}"/>
        <Entry Placeholder="Enter Your Name" Text="{Binding Name, Mode=TwoWay}"/>
        <Button Text="Enter" Command="{Binding EntryCommand}"/>

    </StackLayout>

</ContentPage> 

Now, I don't get any errors but emulator keeps stopping before building the UI:

enter image description here

CodePudding user response:

I think you're using the ViewModel incorrectly.

Depending on your needs,there is no need to create EntryCommand: ICommand.

You can do like this:

public ICommand EntryCommand => new Command(DoSomething);

public void DoSomething() { 
    
        // do some thing here
    }

Besides, the use of Name is also incorrect, you need to create another variable (e.g. private string _name;)

    private string _name;
    public string Name
    {
        set { SetProperty(ref _name, value); }
        get { return _name; }
    }

You can refer to the full sample code here:

   public class MyViewModel: INotifyPropertyChanged
    {
        public ICommand EntryCommand => new Command(DoSomething);

        public MyViewModel() {
            Name = "abc123";

        }
      

        public void DoSomething() { 
        
            // do some thing here
        }



        public string LabelText { get; set; }


        private string _name;
        public string Name
        {
            set { SetProperty(ref _name, value); }
            get { return _name; }
        }



        public void ChangeLabelText()
        {
            if (Name != null)
            {
                LabelText = Name;
            }
        }


        bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
        {
            if (Object.Equals(storage, value))
                return false;

            storage = value;
            OnPropertyChanged(propertyName);
            return true;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string PropertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
        }

    }

When using it in xaml, you can set the BindingContext as follows:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:testapp0211="clr-namespace:TestApp0211"
             x:Class="TestApp0211.MainPage">


    <ContentPage.BindingContext>
        <testapp0211:MyViewModel />
    </ContentPage.BindingContext>

    <StackLayout  BackgroundColor="AliceBlue"
                 Margin="15">

        <Label Text="{Binding Name, Mode=TwoWay}"/>
        <Entry Placeholder="Enter Your Name" Text="{Binding Name, Mode=TwoWay}"/>
        <Button Text="Enter" Command="{Binding EntryCommand}"/>

    </StackLayout>
</ContentPage>

Note:

It is recommended that you rename the class ViewModel (e.g. MyViewModel)to better distinguish between different viewModels.

  • Related