在我使用 MVVM 模式开发的 .NET MAUI 移动应用程序(目标设备:Android)中,当执行从主页到子页面的一些导航以便从某个子页面返回主页时,我点击屏幕顶部栏上显示的默认后退箭头图标。
我的假设是,这样做不会“破坏”/删除页面/视图以及与其关联的视图模型,并且这个假设来自这样的事实:在我的视图模型的构造函数中,我通过 HttpClient 调用 API 端点,这只是简单地插入一个我的 SQL Server 数据库中的记录,当我第一次进入该页面时,数据库中插入的记录为 1,但如果我返回(使用顶部的默认箭头图标),然后返回到同一页面/视图,该函数再次执行(请注意,该函数位于视图模型构造函数内部)相同的记录在数据库中插入两次。
同样适用于 DisplayAlert 方法(同样,所有警报都在视图模型构造函数中),如果这是我第一次在该页面上,则警报会显示一次,但如果我返回并返回应用程序显示警报的次数增加 1。
这是 AppShell 中的路由注册:
public AppShell()
{
InitializeComponent();
Routing.RegisterRoute(nameof(Warehouse), typeof(Warehouse));
}
这是视图的隐藏代码:
public partial class Warehouse: ContentPage
{
private WarehouseViewModel ICvm;
public Warehouse()
{
InitializeComponent();
ICvm = new WarehouseViewModel();
BindingContext = ICvm;
}
}
这是我在主页上执行导航并在点击按钮时执行命令的方式:
await Shell.Current.GoToAsync(nameof(Warehouse));
这是视图模型:
internal class WarehouseViewModel: INotifyPropertyChanged
{
public WarehouseViewModel()
{
MessagingCenter.Subscribe<object, string>(this, "ScannedBarcodeFromMainActivity", async (sender, ScannedBarcode) =>
{
ScannedBarcodeReceived = ScannedBarcode;
bool Insertion_To_DB_Outcome = await MyApiService.Set_PC(ScannedBarcodeReceived);
if (!Insertion_To_DB_Outcome)
{
await App.Current.MainPage.DisplayAlert("Error while inserting", "error while inserting to db :(", "OK");
}
else
{
await App.Current.MainPage.DisplayAlert("Success","Success inserting to db", "OK");
}
});
}
}
我真正想要的是,当我按下默认的后退按钮(顶部的标准箭头图标)时,页面/视图和相关的视图模型会被重置,因此数据库中的插入和警报都只执行一次。
首先要检查的是:在您的 MauiProgran.cs 中,您是否将 ViewModel 声明为 Singleton (
builder.Services.AddSingleton<WarehouseViewModel>
) 或 Transient (builder.Services.AddTransient<WarehouseViewModel>
) ?当您重新加载视图时,单例视图模型不会重置,每次重新生成瞬态时,仅使用视图模型的单个实例。
如果您需要将 ViewModel 保持为单例,关键是在 ContentPage 中定义自定义后退按钮命令:
<Shell.BackButtonBehavior>
<BackButtonBehavior x:DataType="YourViewModel" Command="{Binding BackButtonPressedCommand}"/>
</Shell.BackButtonBehavior>
在您的视图模型中(我使用 MVVM CommunityToolkit 完成此操作,您可以在此处找到有关通用命令的更多信息):
[RelayCommand]
public void BackButtonPressed()
{
// ... Your custom back button behavior, reset the page/view/viemwmodel
Shell.Current.GoToAsync("..");
}