每当我打开一个页面时使用新的ViewModel
我不知道如何更好地标题,所以我想到了解决方案。每当我打开一个页面时使用新的ViewModel
这是问题所在。我有一个包含列表的页面,列表中的每个项目都会打开一个详细信息页面(单击)。但虚拟机被重用,这导致了几个问题。
以前的数据可以在打开的详细信息页面时可以看到的一瞬间
我需要一定的属性设置为特定值时,该页面打开,但由于虚拟机被重新使用它使所有从以前的细节中得到的价值和这使我的逻辑混乱起来。
这个UWP应用程序。我使用Template10框架的NavigationService在页面之间移动。
主页视图模型
public class MainPageViewModel : ViewModelBase {
private List<MangaItem> _mangaList;
public List<MangaItem> mangaList {
get { return _mangaList; }
set { Set(ref _mangaList, value); }
}
private string _mainSearchText;
public string mainSearchText {
get { return _mainSearchText; }
set { Set(ref _mainSearchText, value); }
}
public MainPageViewModel() {
_mangaList = new List<MangaItem>();
mangaList = new List<MangaItem>();
Initialize();
}
private async void Initialize() {
mangaList = await MangaListGet.GetListAsync();
}
public async void MainSearchSubmitted() {
mangaList = await MangaListGet.GetListAsync(_mainSearchText);
}
public void MangaSelected(object sender, ItemClickEventArgs e) {
var mangaItem = (MangaItem)e.ClickedItem;
NavigationService.Navigate(typeof(Views.MangaDetail), mangaItem.id);
}
}
和细节页面视图模型
class MangaDetailViewModel : ViewModelBase {
private MangaItem _mangaDetail;
public MangaItem mangaDetail {
get { return _mangaDetail; }
set { Set(ref _mangaDetail, value); }
}
private string _mangaId;
public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary<string, object> suspensionState) {
_mangaId = parameter as string;
Initialize();
await Task.CompletedTask;
}
private async void Initialize() {
mangaDetail = await MangaDetailGet.GetAsync(_mangaId);
}
public void ChapterSelected(object sender, ItemClickEventArgs e) {
var _chapterId = (ChapterListItem)e.ClickedItem;
NavigationService.Navigate(typeof(Views.ChapterPage), _chapterId.id);
}
}
此代码仅示出了第一个问题是一秒钟显示先前加载的数据。如果需要,我会添加代码来展示其他问题,但我不确定它现在是否真的相关。我在想,也许我的整个逻辑是有缺陷的或什么的。
编辑:
<Page.DataContext>
<vm:ChapterPageViewModel x:Name="ViewModel" />
</Page.DataContext>
其中VM被xmlns:vm="using:MangaReader.ViewModels"
。
尽管Template10文档声明NavigationCacheMode
默认情况下处于禁用状态,但在示例模板(截至编写本文时)情况并非如此。这是在View C#代码(.xaml.cs文件)中设置的。
.xaml.cs文件
namespace MangaReader.Views {
public sealed partial class MangaDetail : Page {
public MangaDetail() {
InitializeComponent();
//NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled; //this was set by default
NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Disabled;
}
}
}
现在,新的视图模型将每次访问此页时创建的。
另一种解决方案是使用Bootstrapper.ResolveforPage(),它旨在处理依赖注入,但很容易满足您的需求。像这样:
[Bindable]
sealed partial class App : BootStrapper
{
static ViewModels.DetailPageViewModel _reusedDetailPageViewModel;
public override INavigable ResolveForPage(Page page, NavigationService navigationService)
{
if (page.GetType() == typeof(Views.DetailPage))
{
if (_reusedDetailPageViewModel == null)
{
_reusedDetailPageViewModel = new ViewModels.DetailPageViewModel();
}
return _reusedDetailPageViewModel;
}
else
{
return null;
}
}
}
NavigationService将对待这与任何其他视图模型相同。这意味着它会调用OnNavTo()并且其他导航覆盖您包含的内容。
祝你好运。
糟糕,我的解决方案字面上做了你所问的相反。 –
我在使用NavigationCacheMode时遇到同样的问题。我删除旧数据并在'OnNavigatedTo'中初始化页面。只需在加载新数据之前删除'DataContext = null;',然后在完成后重新附加它。 –
你能更具体地告诉我如何在我的代码中做到这一点?谢谢。 – rancor1223
我不知道你如何将你的页面绑定到你的视图模型。如果将DataContext设置为Viewmodel,则删除绑定的'DataContext = null;'在ViewModel中设置新Data并使用'DataContext = mangaDetailViewModel'重新附加它。在你的DetailPage的'OnNavigatedTo'中做这件事。 –