我有一个带有选项卡的毛伊岛应用程序。在 DashboardMainPage 上,项目显示在 CollectionView 中。从此页面中,我可以导航到子页面(GoalsPage),其中可以更详细地查看所有项目。在GoalsPage 中,我可以导航到另一个子页面 (CreateGoalPage),其中可以将新目标保存到本地数据库。
导航流程(使用 shell 导航,Shell.Current.GoToAsync):
仪表板主页面 -> 目标页面 -> 创建目标页面
public partial class DashboardMainViewModel : BaseViewModel
{
// The repository to handle CRUD to local db
private readonly IUnitOfWork _unitOfWork;
public ObservableCollection<Goal> Goals { get; } = new ObservableCollection<Goal>();
public DashboardMainViewModel(IUnitOfWork unitOfWork, INavigationService navigationService) : base(navigationService)
{
_unitOfWork = unitOfWork;
}
// This is called from OnAppearing of DashboardMainPage
internal async Task InitializeAsync()
{
if (IsInitialized) // Prevents LoadDataAsync running multiple times when navigate on and navigate back from subpage
{
return;
}
await LoadDataAsync();
}
private async Task LoadDataAsync()
{
Goals.Clear();
var goalsTask = _unitOfWork.Goal.GetAllAsync(_ => _.Completed == false);
Goals.AddRange(goalsTask);
}
[RelayCommand]
private async Task GoToGoalsPage() => await NavigationService.GoToAsync(nameof(GoalsPage));
}
public partial class GoalsViewModel : BaseViewModel
{
private readonly IUnitOfWork _unitOfWork;
public ObservableCollection<Goal> OnGoingGoals { get; } = new ObservableCollection<Goal>();
public ObservableCollection<Goal> CompletedGoals { get; } = new ObservableCollection<Goal>();
public GoalsViewModel(IUnitOfWork unitOfWork, INavigationService navigationService) : base(navigationService)
{
_unitOfWork = unitOfWork;
}
// This is called from OnAppearing of DashboardMainPage
internal async Task InitializeAsync()
{
if (IsInitialized) // Prevents LoadDataAsync running multiple times when navigate on and navigate back from subpage
{
return;
}
await LoadDataAsync();
}
private async Task LoadDataAsync()
{
OnGoingGoals.Clear();
CompletedGoals.Clear();
var goals = await _unitOfWork.Goal.GetAllAsync();
var completed = goals.Where(_ => _.IsCompleted).OrderByDescending(_ => _.Completed.Date);
OnGoingGoals.AddRange(goals.Where(_ => !_.IsCompleted));
CompletedGoals.AddRange(completed);
}
[RelayCommand]
private async Task GoToGoalCreatePage()
{
var goal = new Goal();
var parameters = new Dictionary<string, object> {
{ nameof(Goal), goal }
};
await NavigationService.GoToAsync(nameof(GoalCreatePage), parameters);
}
}
[QueryProperty(nameof(Goal), nameof(Goal))]
[QueryProperty(nameof(IsEdit), nameof(IsEdit))]
public partial class GoalCreateViewModel : BaseViewModel
{
// The repository to handle CRUD to local db
private readonly IUnitOfWork _unitOfWork;
[ObservableProperty]
private Goal _goal;
public GoalCreateViewModel(IUnitOfWork unitOfWork, INavigationService navigationService) : base(navigationService)
{
_unitOfWork = unitOfWork;
}
[RelayCommand]
private async Task Save()
{
var savedGoal = await _unitOfWork.Goal.SaveAsync(Goal);
if (savedGoal is not null)
{
// should I trigger here a weakreference to call item in the both parent vms?
// Navigate back to GoalsPage
await NavigationService.GoBackAsync();
}
}
}
问题 当子子页面中添加了新的目标时,如何更新两个父页面?
还有另一种选择。您可以创建一个 IDateStore 并准备其数据,然后再移动到新的内容页面并在另一个视图模型中接收它。这是示例代码供参考。
public interface IDataStore
{
void AddCalender(CalendarEvent item);
CalendarEvent GetCalendarEvent();
}
//implementation
public class DataStore : IDataStore
{
private CalendarEvent calendarEvent;
public void AddCalender(CalendarEvent item)
{
calendarEvent = item;
}
public CalendarEvent GetCalendarEvent()
{
return calendarEvent;
}
//register singleton
builder.Services.AddSingleton<IDataStore, DataStore>();
//Prepare data for another viewmodel
var dataStore = serviceProvider.GetService<IDataStore>();
dataStore?.AddCalender(item);
var popup = serviceProvider.GetService<EventDetailPopup>();
popupService.ShowPopup(popup);
//Received another viewmodel
public partial class EventDetailsViewModel:BaseViewModel
{
[ObservableProperty]
private CalendarEvent item;
public EventDetailsViewModel(IDataStore dataStore)
{
Item = dataStore.GetCalendarEvent();
}