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

发布于 2025-01-09 16:43:15 字数 4524 浏览 0 评论 0原文

我使用 MVVM 在 Xamarin.Forms 应用程序中实现了一个具有四个输入元素的表单。这四个元素对应于模型类的四个属性。

数据存储在本地 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 文件中的事件处理程序进行的,我想将其删除并替换为 Update在 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 文件中编写相应实现的帮助。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

鼻尖触碰 2025-01-16 16:43:15

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

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

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();
            }
        }
    }
凉城已无爱 2025-01-16 16:43:15

如果我们正确使用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.csLabWork的对象> 作为传递给 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);
    }

If we use MVVM correctly, we don't need to assign values to entry and datePicker every time, or get the values from each control ourself.

Based on your code ,I created a simple demo to simulate your requirement.

You can refer to the following code:

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

Here I created a object of LabWork in App.xaml.cs as a parameter passed to 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);
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文