>我有一个选项卡式页面,显示正在进行的交付和已完成的交付。两个视图的模型是相同的,只是我们获取数据的服务方法不同,所以我想重用 ViewModel。
通过将一些导航数据传递到我的 InitializeAsync 方法中来重用 ViewModel,这将允许我决定使用哪种服务方法来获取视图的数据,这将是一个很好的解决方案吗?
我会在选项卡式页面视图的代码隐藏中覆盖 OnCurrentPageChanged 并从那里初始化视图模型
TabbedPageView.xaml.cs
protected override async void OnCurrentPageChanged()
{
base.OnCurrentPageChanged();
if (!(CurrentPage.BindingContext is TabbedPageViewModel tabbedPageViewModel)) return;
if (CurrentPage == DeliveriesInProgress)
{
await tabbedPageViewModel.InitializeAsync("DeliveriesInProgress");
}
else if (CurrentPage == FinishedDeliveries)
{
await tabbedPageViewModel.InitializeAsync("FinishedDeliveries");
}
}
选项卡式页面视图模型.cs
public async Task InitializeAsync(object navigationData)
{
if (navigationData is string deliveryType)
{
if (deliveryType == "InProgress")
{
Deliveries = await _deliveryService.GetDeliveriesInProgress();
}
else if (deliveryType == "Finished")
{
Deliveries = await _deliveryService.GetFinishedDeliveries();
}
}
}
什么是替代解决方案?
最好的方法是在视图模型中使用两个不同的属性。然后,可以将选项卡中的两个不同视图绑定到关联的属性。
在您的视图中模型:
public ObservableCollection<MyDeliveryModel> FinishedDeliveries;
public ObservableCollection<MyDeliveryModel> DeliveriesInProgress;
知道您可以添加两种方法来加载这些属性的数据:
public async Task RefreshFinishedAsync()
{
// Your logic to load the data from the service
}
public async Task RefreshInProgressAsync()
{
// Your logic to load the data from the service
}
然后在您的选项卡式页面事件中:
if (CurrentPage == DeliveriesInProgress)
{
await tabbedPageViewModel.RefreshInProgressAsync();
}
else if (CurrentPage == FinishedDeliveries)
{
await tabbedPageViewModel.RefreshFinishedAsync();
}
使用此解决方案,您可以分离数据,并且无需在每次更改选项卡时重新加载整个数据。您可以检查集合中是否已经有一些数据,如果有...只是不要重新加载数据。如果用户需要,就这样做。
这提高了用户的性能和"等待时间"。
或者作为替代方案:一次加载所有数据,并仅筛选两个集合属性的数据。这减少了服务呼叫。
您可以通过对使用该基础视图的每个选项卡使用基础视图模型和视图模型来实现此目的。 然后,基地保存您的命令和交付。 将每个选项卡式页面绑定到该页面的视图模型,因此无需检查选项卡已更改。 构造每个视图模型时,传入基础所需的信息,以了解如何查询数据。 对于每个选项卡式视图,如果正在进行的视图和已完成视图相同,请使用部分视图并将其放在两个选项卡式页面中。 从长远来看,这提供了灵活性。
public class InProgressDeliveriesViewModel: BaseDeliveryViewModel{
public InProgressDeliveriesViewModel():base(filterParams){}
}
public class FinishedDeliveriesViewModel: BaseDeliveryViewModel{
public FinishedDeliveriesViewModel():base(filterParams){}
}
public class BaseDeliveryViewModel{
private FilterObjectOfSomeSort _filterParams;
public BaseDeliveryViewModel(filterParams whatever){
//use these params to filter for api calls, data. If you are calling the same
//endpoint pass up the filter
_filterParams = whatever;
}
public ObservableCollection<MyDeliveryModel> Deliveries {get;set;}
public async Task LoadDeliveries(){
//use the filter params to load correct data
var deliveries = await apiClient.GetDeliveries(filterParams); //however you
//are gathering data
}
.... All of your other commands
}