【发布时间】:2021-05-29 13:24:52
【问题描述】:
这在某种程度上类似于Bind Two Different Views for same ViewModel 这样的重复问题 但我在 AppShell 上显示页面并遇到与数据相关的问题:
<FlyoutItem Title="News & Updates" Icon="icon_feed.png" >
<Tab x:Name="UriUpdates" Title="News & Updates" >
<ShellContent Title="News" Route="NewsPage" ContentTemplate="{DataTemplate local:NewsPage}" />
<ShellContent Title="Notifications" Route="NotificationsPage" ContentTemplate="{DataTemplate local:NotificationsPage}" />
</Tab>
</FlyoutItem>
两个页面都使用 ContentView 类型的自定义控件。 在页面的代码隐藏中,我提供了 BindingContext
BindingContext = _viewModel = new UpdatesViewModel("news");
BindingContext = _viewModel = new UpdatesViewModel("notifications");
ViewModel 有一个属性 UpdateType,它在构造函数中更新,它的值在命令(ExecuteLoadItemsCommand)中用于填写列表(Items):
Items = new ObservableCollection<UpdatesModel>();
LoadItemsCommand = new Command(async () => await ExecuteLoadItemsCommand());
ExecuteLoadItemsCommand() 事件导致 VM 从 DataStore 填充数据
public IDataStore<UpdatesModel> DataStore => DependencyService.Get<IDataStore<UpdatesModel>>();
ExecuteLoadItemsCommand 被按预期调用并每次都填充相应的项目。
async Task ExecuteLoadItemsCommand()
{
IsBusy = true;
try
{
Items.Clear();
var items = await DataStore.GetItemsAsync(UpdateType);
if(items!=null)
foreach (var item in items)
{
Items.Add(item);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
finally
{
IsBusy = false;
}
}
GetItemsAsync 在返回所需项目列表的 DataStore 中:
public async Task<IEnumerable<UpdatesModel>> GetItemsAsync(string updateType, bool forceRefresh = false)
{
if (forceRefresh || items == null || items.Count == 0)
{
Uri uri = new Uri(Constants.GetUpdatesUrl(updateType));
try
{
HttpResponseMessage response = await client.GetAsync(uri);
if (response.IsSuccessStatusCode)
{
string content = await response.Content.ReadAsStringAsync();
items = (List<UpdatesModel>)JsonConvert.DeserializeObject<IEnumerable<UpdatesModel>>(content);
}
}
catch (Exception ex)
{
Debug.WriteLine(@"\tERROR {0}", ex.Message);
}
}
return await Task.FromResult(items);
}
我认为,每当为页面 News/Notifications 填充项目时,它不能为每次选项卡更改单击一次又一次地调用 Rest-Service。它应该在需要时更新项目。 因此,为此我在 DataStore 的方法 GetItemsAsync 中应用了一个条件(它是 IDataStore 的实现)作为
if (forceRefresh || items == null || items.Count == 0)
{
//Rest Service Call to fill items list
}
问题是项目(这是 VM 中的一个属性)总是非空的,并且填充了第一页数据(新闻项目)。 NewsPage 加载后,不知道为什么在加载NotificationsPage 时项目不为空,并且被NewsPage 数据填充。
请帮我看看我是否在为不同的视图共享 VM 方面存在不好的做法,还是存在某些问题导致页面具有由第一页填充的数据?
【问题讨论】:
-
更新类型或更新模型?因为我在您的代码中没有看到 UpdateType。物品或物品?我认为您应该包含更多代码我认为我们不能仅从您共享的内容中看到整个画面。
-
感谢您的回复。当 BindingContext = _viewModel = new UpdatesViewModel("news");正在被调用,viewModel 有一个属性 UpdateType,用于从休息服务获取相应的数据,正如我所提到的,这个 UpdateType(新闻/通知)正在 ExecuteLoadItemsCommand 中使用
-
当我在每次调用 ExecuteLoadItemsCommand 时允许填充项目时一切正常,但是当我在项目为空的情况下强制填充项目时,问题就来了。对于第一页项目因为它是空的而被填充,对于下一个选项卡,当相同的 VM 用于第二页时,它显示项目不是空的,并且第二页也获得了与第一页填充的相同的项目列表
-
@Cfun 可以在必要的时候清除项目,但问题是为什么项目已经为具有相同 VM 的第二页填充?在加载第一页(NewsPage)时进行调试时,项目已填充,但在加载第二页时,项目不为空,并且具有先前填充项目的数据。
-
项目在 ContentView 中显示为
<CollectionView x:Name="ItemsListView" ItemsSource="{Binding Items}" SelectionMode="None">
标签: c# xamarin.forms mvvm viewmodel