'Update form with more than one parameter through binding in MVVM

I implemented a form with four input elements in a Xamarin.Forms app with MVVM. The four elements correspond to four properties of a model class.

Data is stored in a local SQLite database. I managed to deal with the creation, reading and deletion of data, but I am stuck with updating it. The problem I have is that I want to execute a command to perform the update with binding with more than one parameter. I tried several things, to no avail. So I came back to what worked last.

Model

public class LabWork
    {
        [PrimaryKey, AutoIncrement]
        public int LabWorkId { get; set; }
        public DateTime DateLabWork { get; set; }
        public string TestName { get; set; }
        public float TestValue { get; set; }
        public string TestUnit { get; set; }
    }

View

<ContentPage.Resources>
        <ResourceDictionary>
            <vm:LabWorkDetailVM x:Key="vm"/>
        </ResourceDictionary>
    </ContentPage.Resources>
    
    <ContentPage.Content>
        <StackLayout>

            <DatePicker x:Name="dateLabWorkPicked"
                        Format="dd/MM/yyyy"
                        FontSize="Large"
                        Margin="30,0,0,0"
                        />

            <Entry x:Name="testName"
                   Margin="25,0,0,0"
                   />

            <Entry x:Name="testValue"
                   Margin="25,0,0,0"
                   FontSize="Large"
                   Keyboard="Numeric"
                   />

            <Entry x:Name="testUnit"
                   Margin="25,0,0,0"
                   FontSize="Large"
                   Placeholder="Ex. mg/l, μg/l..."
                   />

            <Button Text="Sauvegarder modifications"
                    x:Name="updateLabWorkButton"
                    Command="{Binding Source={StaticResource vm}, Path=UpdateCommand}"
                    CommandParameter={?????}/>
            
            <Button Text="Effacer"
                    x:Name="deleteLabWorkButton"
                    Command="{Binding Source={StaticResource vm}, Path=DeleteCommand}" />

        </StackLayout>
    </ContentPage.Content>

ViewModel

public class LabWorkDetailVM
    {
        public Command DeleteCommand { get; set; }
        public Command UpdateCommand { get; set; }
        public LabWork SelectedLabWork { get; set; }
        public LabWorkDetailVM()
        {
            DeleteCommand = new Command(Delete);
            UpdateCommand = new Command(Update);
        }

        private void Update(object obj)
        {
            throw new NotImplementedException();
        }

        private void Delete()
        {
            using (SQLiteConnection conn = new SQLiteConnection(App.DatabaseLocation))
            {
                conn.CreateTable<LabWork>();
                int rows = conn.Delete(SelectedLabWork);
                App.Current.MainPage.Navigation.PopAsync();
            }
        }
    }

So far updating works from an event handler in View .xaml.cs file below, which I want to remove and replace with Update in the ViewModel

public partial class LabWorkDetailPage : ContentPage
    {
        public LabWork selectedLabWork;
        public LabWorkDetailPage(LabWork selectedLabWork)
        {
            InitializeComponent();

            (Resources["vm"] as LabWorkDetailVM).SelectedLabWork = selectedLabWork;

            this.selectedLabWork = selectedLabWork;

            dateLabWorkPicked.Date = selectedLabWork.DateLabWork;
            testName.Text = selectedLabWork.TestName;
            testValue.Text =  selectedLabWork.TestValue.ToString();
            testUnit.Text = selectedLabWork.TestUnit;
        }

        private void UpdateLabWorkButton_Clicked(object sender, EventArgs e)
        {
            selectedLabWork.DateLabWork = dateLabWorkPicked.Date;
            selectedLabWork.TestName = testName.Text;
            selectedLabWork.TestValue = float.Parse(testValue.Text, CultureInfo.InvariantCulture.NumberFormat);
            selectedLabWork.TestUnit = testUnit.Text;

            using (SQLiteConnection conn = new SQLiteConnection(App.DatabaseLocation))
            {
                conn.CreateTable<LabWork>();
                int rows = conn.Update(selectedLabWork);
                Navigation.PopAsync();

                //if (rows > 0)
                //    DisplayAlert("Success", "Experience successfully updated", "OK");
                //else
                //    DisplayAlert("Failure", "Failed to update experience", "OK");
            }
        }
    }

I'd appreciate some help on how to write the Update method in the ViewModel and corresponding implementation in the View xaml file.



Solution 1:[1]

i will implement binding as you asked in the comment.

<StackLayout BindableLayout.ItemsSource="{Binding LabWorkTest}"
             >
    <BindableLayout.ItemTemplate>
        <DataTemplate>
            

            <Entry x:Name="testName"
                   Margin="25,0,0,0"
                   Text={Binding TestName , Mode = TwoWays}/>

         

            <Button Text="Sauvegarder modifications"
                    x:Name="updateLabWorkButton"
                    Command="{Binding Source={StaticResource vm}, Path=UpdateCommand}"
                    CommandParameter={Binding .}/>
        

        </StackLayout>
        </DataTemplate>
    </BindableLayout.ItemTemplate>
</StackLayout>

in the VM :

public class LabWorkDetailVM
    {
        public Command DeleteCommand { get; set; }
        public Command UpdateCommand { get; set; }
        public LabWork SelectedLabWork { get; set; }
         
        private LabWork _labWorkTest;
        public LabWork LabWorkTest{
         get{ return _labWorkTest;}
         set{ _labWorkTest= value; OnPropertyChanged("LabWork");}
         }


public LabWorkDetailVM()
        {
            LabWorkTest = new LabWork{ ...};
            DeleteCommand = new Command(Delete);
            UpdateCommand = new Command<object>(Update);
        }

        private void Update(object obj)
        {

            LabWork _labWork =(LabWork) obj;
        }

        private void Delete()
        {
            using (SQLiteConnection conn = new SQLiteConnection(App.DatabaseLocation))
            {
                conn.CreateTable<LabWork>();
                int rows = conn.Delete(SelectedLabWork);
                App.Current.MainPage.Navigation.PopAsync();
            }
        }
    }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1