我有一个TabbedPage,其中显示了进行中的交货和已完成的交货。两种视图的模型相同,只是从中获取数据的服务方法不同,所以我想重用ViewModel。
通过将一些导航数据传递到InitializeAsync方法中来重用ViewModel,这将是一个很好的解决方案,该方法可以让我决定使用哪种服务方法来获取视图数据?
我会在TabbedPage View的代码中覆盖OnCurrentPageChanged并从那里初始化ViewModel
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");
}
}
TabbedPageViewModel.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();
}
}
}
什么是替代解决方案?
答案 0 :(得分:2)
最好的方法是在视图模型中使用两个不同的属性。然后,可以将选项卡中的两个不同视图绑定到关联的属性。
在您的视图模型中:
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
}
然后在您的TabbedPage-Event中:
if (CurrentPage == DeliveriesInProgress)
{
await tabbedPageViewModel.RefreshInProgressAsync();
}
else if (CurrentPage == FinishedDeliveries)
{
await tabbedPageViewModel.RefreshFinishedAsync();
}
使用此解决方案,您可以分离数据,并且不必每次更改选项卡时都重新加载整个数据。您可以检查集合中是否已经有数据,如果有的话...只是不重新加载数据。只要用户想要,就做。
这可以提高用户的性能和“等待时间”。
或替代: 一次加载所有数据,仅过滤两个collection-properties的数据。这样可以减少服务呼叫。
答案 1 :(得分:1)
您可以通过使用基础视图模型和使用基础视图的每个选项卡的视图模型来完成此操作。基地然后保存您的命令和交付。您将每个选项卡式页面绑定到该页面的视图模型,因此您无需检查更改的选项卡。构造每个视图模型时,请传递基础知识所需的信息以了解如何查询数据。对于每个选项卡式视图,如果进行中和完成的视图相同,请使用部分视图并将其放在两个选项卡式页面中。从长远来看,这提供了灵活性。
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
}