问题描述
更新 - 问题 #1 已解决,问题 #2 仍未解决 您可以在 https://www.youtube.com/watch?v=5_6KJ0QJouM
查看我的问题的非常粗略的演示视频我正在使用 MVVM 设计模式和 C# 构建带有 sqlite 数据库的 Xamarin.Forms 应用程序>
当尝试将记录从 View
保存到数据库时,更新/保存似乎没有保存到 sqlite 数据库或反映在其他 Views
中。
我知道数据库 Save
方法确实有效,因为我在应用程序首次使用 App.xaml.cs
文件加载(在 DeveloperData.cs
中)时创建了一些虚拟数据。
我有两个问题。
(已解决)问题 1 - 数据未保存到数据库
当我从使用 Save
viewmodel 的 MerchandiserEditPage.xaml
调用 MerchandiserEditPageviewmodel.cs
命令时,记录似乎没有保存。
问题 2 - 反映在其他视图中的变化
将更新的数据保存到数据库后,如何在其他视图中反映该更改?在我从 MerchandiserEditPage
保存一条记录后,View
从堆栈中“弹出”并且用户返回到 MerchandiserProfileView
。我希望更新的数据反映在堆栈上的所有其他视图中。但这似乎没有发生? (我使用硬编码数据对此进行了测试,并且发生了同样的问题,因此问题与问题 1 没有直接关系)
我的项目中有很多文件,可以从我的 GitHub repository 查看/下载,但我将在这个问题中集中讨论以下内容。
- MerchandiserEditPage.xaml(查看)
- MerchandiserProfilePage.xaml(查看)
- MerchandiserDatabase.cs(数据库函数)x
- MerchandiserEditPageviewmodel.cs x
查看我的 GitHub repository 以了解完整项目。
MerchandiserDatabase.cs(数据库功能)
using sqlite;
namespace MobileApp.Database
{
public class MerchandiserDatabase
{
private static sqliteConnection database = DependencyService.Get<IDatabaseConnection>().DbConnection();
private readonly static object collisionLock = new object();
public MerchandiserDatabase()
{
database.CreateTable<Models.Merchandiser>();
}
public static void SaveMerchandiser(Models.Merchandiser merchandiser)
{
lock (collisionLock)
{
if (merchandiser.Id != 0)
{
database.Update(merchandiser);
}
else
{
database.Insert(merchandiser);
}
}
}
}
}
MerchandiserEditPageviewmodel.cs(viewmodel)更新
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms;
namespace MobileApp.viewmodels
{
public class MerchandiserEditPageviewmodel : Baseviewmodel
{
public string PageTitle { get; } = "Edit Merchandiser Profile";
public Command SaveCommand { get; set; }
private string name;
public string Name
{
get { return name; }
set
{
name = value;
OnPropertyChanged();
}
}
private string phone;
public string Phone
{
get { return phone; }
set
{
phone = value;
OnPropertyChanged();
}
}
private string email;
public string Email
{
get { return email; }
set
{
email = value;
OnPropertyChanged();
}
}
public MerchandiserEditPageviewmodel(Models.Merchandiser selectedMerchandiser)
{
Name = selectedMerchandiser.Name;
Phone = selectedMerchandiser.Phone;
Email = selectedMerchandiser.Email;
SaveCommand = new Command( async ()=> {
selectedMerchandiser.Name = this.Name;
selectedMerchandiser.Phone = this.Phone;
selectedMerchandiser.Email = this.Email;
Database.MerchandiserDatabase.SaveMerchandiser(selectedMerchandiser);
await Application.Current.MainPage.Navigation.PopModalAsync();
});
}
}
}
MerchandiserEditPage.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"
x:Class="MobileApp.Views.MerchandiserEditPage">
<ContentPage.Content>
<StackLayout>
<!--Page heading-->
<StackLayout Spacing="0">
<Label Text="{Binding PageTitle}"
Style="{StaticResource PageTitle}"/>
<BoxView HeightRequest="1" Color="LightGray" />
</StackLayout>
<!-- Merchandiser Profile -->
<StackLayout Margin="10">
<Label Text="Name"/>
<Entry Text="{Binding Name}"/>
<Label Text="Phone"/>
<Entry Text="{Binding Phone}"/>
<Label Text="Email"/>
<Entry Text="{Binding Email}"/>
<StackLayout Orientation="Horizontal"
HorizontalOptions="Center">
<Button Text="Cancel"
Clicked="CancelButton_Clicked"/>
<Button Text="Save"
Command="{Binding SaveCommand}"/>
</StackLayout>
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
MerchandiserEditPage.xaml.cs(查看 - 代码隐藏)
public partial class MerchandiserEditPage : ContentPage
{
Models.Merchandiser SelectedMerchandiser { get; set; }
public MerchandiserEditPage (Models.Merchandiser selectedMerchandiser)
{
InitializeComponent ();
SelectedMerchandiser = selectedMerchandiser;
this.BindingContext = new viewmodels.MerchandiserEditPageviewmodel(selectedMerchandiser);
}
async private void CancelButton_Clicked(object sender,EventArgs e)
{
await Navigation.PopModalAsync();
}
}
MerchandiserProfilePage.xaml(视图 - 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"
x:Class="MobileApp.Views.MerchandiserProfilePage"
NavigationPage.HasNavigationBar="False">
<ContentPage.Content>
<StackLayout>
<!--Page heading-->
<StackLayout Spacing="0">
<Label Text="{Binding PageTitle}"
Style="{StaticResource PageTitle}"/>
<BoxView HeightRequest="1" Color="LightGray" />
</StackLayout>
<!-- Merchandiser Profile -->
<StackLayout Margin="10">
<Label Text="Name"/>
<Entry Text="{Binding Name}"
IsEnabled="False"/>
<Label Text="Phone"/>
<Entry Text="{Binding Phone}"
IsEnabled="False"/>
<Label Text="Email"/>
<Entry Text="{Binding Email}"
IsEnabled="False"/>
<StackLayout Orientation="Horizontal"
HorizontalOptions="Center">
<Button Text="Back"
Clicked="BackButton_Clicked"/>
<Button Text="Edit"
Clicked="EditButton_Clicked"/>
</StackLayout>
<Button Text="Delete"
Command="{Binding DeleteCommand}"/>
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
MerchandiserProfilePage.xaml.cs -(查看 - 代码隐藏)
public partial class MerchandiserProfilePage : ContentPage
{
private Models.Merchandiser SelectedMerchandister { get; set; }
public MerchandiserProfilePage (Models.Merchandiser selectedMerchandiser)
{
InitializeComponent ();
SelectedMerchandister = selectedMerchandiser;
this.BindingContext = new viewmodels.MerchandiserProfilePageviewmodel(selectedMerchandiser);
}
async private void BackButton_Clicked(object sender,EventArgs e)
{
await Navigation.PopModalAsync();
}
async private void EditButton_Clicked(object sender,EventArgs e)
{
await Navigation.PushModalAsync(new Views.MerchandiserEditPage(SelectedMerchandister));
}
}
MerchandiserProfilePageviewmodel.cs(视图模型)
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms;
namespace MobileApp.viewmodels
{
public class MerchandiserProfilePageviewmodel : Baseviewmodel
{
public string PageTitle { get; } = "Merchandiser Profile";
public Command DeleteCommand { get; }
private string name;
public string Name
{
get { return name; }
set
{
name = value;
OnPropertyChanged();
}
}
private string phone;
public string Phone
{
get { return phone; }
set
{
phone = value;
OnPropertyChanged();
}
}
private string email;
public string Email
{
get { return email; }
set
{
email = value;
OnPropertyChanged();
}
}
public MerchandiserProfilePageviewmodel(Models.Merchandiser selectedMerchandiser)
{
Name = selectedMerchandiser.Name;
Phone = selectedMerchandiser.Phone;
Email = selectedMerchandiser.Email;
DeleteCommand = new Command( async()=> {
bool deleteConfirmed = await Application.Current.MainPage.displayAlert("Confirm Delete",$"Are you sure you want to delete {selectedMerchandiser.Name} as a Merchandiser?","Yes","No");
if (deleteConfirmed)
{
// Todo: Delete Merchandiser
await Application.Current.MainPage.Navigation.PopModalAsync();
}
});
}
}
}
解决方法
您的虚拟机中有一组硬编码的数据,而不是从数据库中加载数据
public MerchandisersPageViewModel()
{
//Merchandisers = new ObservableCollection<Models.Merchandiser>(Database.MerchandiserDatabase.GetMerchandisers());
Merchandisers = new ObservableCollection<Models.Merchandiser>()
{
new Models.Merchandiser { Id=1,Name="Barney Rubble",Phone="021 321 654",Email="barney@rubble.com"},new Models.Merchandiser { Id=2,Name="Frank Grimes",Phone="022 456 789",Email="grimey@homersfriend.com"},new Models.Merchandiser { Id=3,Name="Perry Platypus",Phone="023 789 456",Email="perry@agentp.com"},};
}
更新:
在MerchandiserProfilePageViewModel
中,去掉Name
、Phone
和EMail
的属性
然后在 MerchandiserProfilePage.xaml
中更改绑定
<Entry Text="{Binding SelectedMerchandiser.Name}" IsEnabled="False"/>