bmartin042503
bmartin042503

Reputation: 133

Command parameter always returning null - Xamarin Forms

I'm trying to make an app where I save subjects and tasks in a local database. I'm stuck when I add a new task. I made a command for the NewTaskPage and it is always returning a null value, while it should return an object of task (STask).

I couldn't find anything helpful. What's wrong with the code?

XAML code (NewTaskPage):

<?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.ShellPages.NewTaskPage"
             Shell.FlyoutBehavior="Disabled">
    <StackLayout x:Name="newTaskStackLayout">
        <Label FontSize="Large" Text="Add a new task"/>
        <Entry Placeholder="Name" Text="{Binding Name, Mode=TwoWay}"/>
        <Picker ItemsSource="{Binding SubjectList}" ItemDisplayBinding="{Binding Name}"
                SelectedIndex="{Binding Index, Mode=TwoWay}"/>
        <CheckBox IsChecked="{Binding IsDeadline, Mode=TwoWay}" />
        <DatePicker Date="{Binding Date, Mode=TwoWay}" IsEnabled="{Binding DateEnabled}"/>
        <Button Text="Save" Command="{Binding NewTaskCommand}" 
                CommandParameter="{Binding Stask}"/>
    </StackLayout>
</ContentPage>

ViewModel:

namespace MyApp.ViewModel
{
    public class NewTaskViewModel : INotifyPropertyChanged
    {
        private STask stask;
        public STask Stask
        {
            get { return stask; }
            set
            {
                stask = value;
                OnPropertyChanged(nameof(Stask));
            }
        }
        public NewTaskCommand NewTaskCommand { get; set; }
        public List<Subject> SubjectList { get; set; }
        public NewTaskViewModel()
        {
            Stask = new STask();
            SubjectList = new List<Subject>();
            InitializeSubjectList();
            NewTaskCommand = new NewTaskCommand(this);
        }

        public async void InitializeSubjectList()
        {
            var subjects = await SubjectServices.GetSubjects();
            SubjectList.Clear();
            foreach (var subject in subjects)
                SubjectList.Add(subject);
        }

        private DateTime date;
        public DateTime Date
        {
            get { return date; }
            set
            {
                date = value;
                Stask = new STask()
                {
                    Name = this.Name,
                    IsDeadline = this.IsDeadline,
                    DeadLine = this.Date,
                    SubjectID = SubjectList[this.Index].ID
                };
                OnPropertyChanged(nameof(Date));
            }
        }

        private bool isdeadline;
        public bool IsDeadline
        {
            get { return isdeadline; }
            set
            {
                isdeadline = value;
                Stask = new STask()
                {
                    Name = this.Name,
                    IsDeadline = this.IsDeadline,
                    DeadLine = this.Date,
                    SubjectID = SubjectList[this.Index].ID
                };
                DateEnabled = value;
                OnPropertyChanged(nameof(IsDeadline));
            }
        }

        private bool dateenabled;
        public bool DateEnabled
        {
            get { return dateenabled; }
            set
            {
                dateenabled = value;
                Stask = new STask()
                {
                    Name = this.Name,
                    IsDeadline = this.IsDeadline,
                    DeadLine = this.Date,
                    SubjectID = SubjectList[this.Index].ID
                };
                OnPropertyChanged(nameof(DateEnabled));
            }
        }

        private string name;
        public string Name
        {
            get { return name; }
            set
            {
                name = value;
                Stask = new STask()
                {
                    Name = this.Name,
                    IsDeadline = this.IsDeadline,
                    DeadLine = this.Date,
                    SubjectID = SubjectList[this.Index].ID
                };
                OnPropertyChanged(nameof(Name));
            }
        }

        private int index;
        public int Index
        {
            get { return index; }
            set
            {
                index = value;
                Stask = new STask()
                {
                    Name = this.Name,
                    IsDeadline = this.IsDeadline,
                    DeadLine = this.Date,
                    SubjectID = SubjectList[this.Index].ID
                };
                OnPropertyChanged(nameof(Index));
            }
        }


        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged == null)
                return;

            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        public async void SaveTask(STask s)
        {
            int rows = 0;
            rows = await STaskServices.AddTask(s);
            if (rows > 0)
                await App.Current.MainPage.DisplayAlert("Debug", $"Task successfully saved!\nName: {s.Name}", "Ok");
            else
                await App.Current.MainPage.DisplayAlert("Error", "An error has occured while saving the task!", "Ok");
        }
    }
}

NewTaskCommand: (for NewTaskViewModel)

namespace MyApp.ViewModel.Commands
{
    public class NewTaskCommand : ICommand
    {
        public NewTaskViewModel NewTaskViewModel;
        public NewTaskCommand(NewTaskViewModel ntvm)
        {
            this.NewTaskViewModel = ntvm;
        }
        public event EventHandler CanExecuteChanged;

        public bool CanExecute(object parameter)
        {
            //parameter is null
            string param = parameter as string;
            var task = (STask)parameter; 
            if (task == null) //even with this, i still have an exception
                return false;

            if(string.IsNullOrEmpty(task.Name)) 
                return false;

            return true;
        }

        public void Execute(object parameter)
        {
            STask s = parameter as STask;
            NewTaskViewModel.SaveTask(s);
        }
    }
}

I appreciate any kind of help!

Upvotes: 1

Views: 644

Answers (2)

Gertjan Brouwer
Gertjan Brouwer

Reputation: 1016

Your problem lies with the properties: IsDeadline, DateEnabled, Name and Index. When the user inputs a different name you edit the name and you change the Stask. However, you only call OnPropertyChanged for the name and not of the Stask. Thus your binding to Stask in CommandParameter is not getting updated. Add OnPropertyChanged(nameof(Stask)); to each of these properties and it should work.

Upvotes: 0

bmartin042503
bmartin042503

Reputation: 133

I've found a solution. I put this in my XAML code:

xmlns:viewmodel="clr-namespace:MyApp.ViewModel" 
         x:DataType="viewmodel:NewTaskViewModel"

Upvotes: 1

Related Questions