通过在 MVVM 中绑定更新具有多个参数的表单

Update form with more than one parameter through binding in MVVM

我使用 MVVM 在 Xamarin.Forms 应用程序中实现了一个包含四个输入元素的表单。四个元素对应一个模型的四个属性class.

数据存储在本地 SQLite 数据库中。我设法处理了数据的创建、读取和删除,但我坚持更新它。我遇到的问题是我想执行一个命令来执行与多个参数绑定的更新。我尝试了几件事,但无济于事。所以我回到了最后的工作。

型号

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; }
    }

查看

<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();
            }
        }
    }

到目前为止,更新是从下面的 View.xaml.cs 文件中的事件处理程序开始的,我想删除它并替换为 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");
            }
        }
    }

对于如何在 ViewModel 中编写 Update 方法以及在 View xaml 文件中编写相应的实现,我将不胜感激。

我将按照您在评论中的要求实现绑定。

<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>

在虚拟机中:

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();
            }
        }
    }

如果我们正确使用MVVM,就不需要每次都给entry和datePicker赋值,或者自己从各个控件中取值。

根据您的代码,我创建了一个简单的演示来模拟您的要求。

您可以参考以下代码:

MainPage.xaml.cs

public partial class MainPage : ContentPage
{
    public LabWork selectedLabWork;


    LabWorkDetailVM mViewModel;
    public MainPage(LabWork selectedLabWork)
    {
        InitializeComponent();

        this.selectedLabWork = selectedLabWork;

        mViewModel = new LabWorkDetailVM();
        mViewModel.SelectedLabWork = selectedLabWork; 

        this.BindingContext = mViewModel;

       
    }
}

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" xmlns:vm="clr-namespace:FormApp225"
             x:Class="FormApp225.MainPage">


    <ContentPage.Content>
        <StackLayout>

            <DatePicker x:Name="dateLabWorkPicked"
                        Format="dd/MM/yyyy"
                        FontSize="Large"
                        Margin="30,0,0,0"
                        Date="{Binding SelectedLabWork.DateLabWork}"
                        />

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

            <Entry x:Name="testValue"
                   Margin="25,0,0,0"
                   FontSize="Large"
                   Keyboard="Numeric"
                   
                   Text="{Binding SelectedLabWork.TestValue}"
                   />

            <Entry x:Name="testUnit"
                   Margin="25,0,0,0"
                   FontSize="Large"
                   Text="{Binding SelectedLabWork.TestUnit}"
                   Placeholder="Ex. mg/l, μg/l..."
                   />

            <Button Text="Update"
                    x:Name="updateLabWorkButton"
                    Command="{Binding UpdateCommand}"
                    />

                <Button Text="delete"
                    x:Name="deleteLabWorkButton"
                    Command="{Binding DeleteCommand}" />

        </StackLayout>
    </ContentPage.Content>

</ContentPage>

LabWorkDetailVM.cs

   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()
        {
            Debug.WriteLine("Update ------------>" + "DateLabWork = " + SelectedLabWork.DateLabWork.ToString() + "<--> TestName = " + SelectedLabWork.TestName + " <---> TestValue = " + SelectedLabWork.TestValue + "<---- > TestUnit = " + SelectedLabWork.TestUnit);

            // here  the value of SelectedLabWork is the latest, you can update it  into your database

        }

        private void Delete()
        {
            System.Diagnostics.Debug.WriteLine("Delete ------------>");

            
        }
    }

App.xaml.cs

这里我在App.xaml.cs中创建了一个LabWork的对象作为传递给MainPage的参数。

    public App()
    {
        InitializeComponent();

        LabWork selectedLabWork =  new LabWork {DateLabWork= new DateTime(2022, 1, 1), LabWorkId = 1, TestName = "name1", TestValue = 1, TestUnit = "TestUnit1" };

        MainPage = new MainPage(selectedLabWork);
    }