通过在 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);
}
我使用 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);
}