c# - 每次打开页面时都使用新的 ViewModel

标签 c# mvvm uwp template10

我不知道如何更好地表达标题,所以我选择了我想到的解决方案。

这是问题所在。我有一个包含列表的页面,列表中的每个项目都会打开一个详细信息页面(单击时)。但是虚拟机被重用了,这给我带来了几个问题。

  • 打开详细页面时可以看到之前的数据瞬间
  • 当页面打开时,我需要将某些属性设置为特定值,但是由于 VM 被重用,它保留了之前细节中的所有值,这弄乱了我的逻辑。

  • 这个 UWP 应用。我正在使用 Template10 框架的 NavigationService 在页面之间移动。

    主页 View 模型
    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);
        }
    } 
    

    和详情页ViewModel
    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" .

    最佳答案

    另一种解决方案是使用 Bootstrapper.ResolveforPage() ,它旨在处理依赖注入(inject),但很容易满足您的需求。像这样:

    [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 会将其视为与任何其他 View 模型相同。这意味着它将调用 OnNavTo() 和您包含的其他导航覆盖。

    祝你好运。

    关于c# - 每次打开页面时都使用新的 ViewModel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40780795/

    相关文章:

    c# - 选项卡上的文本框 SelectAll 但不是鼠标单击

    c# - 为什么 TreeView 控件不绑定(bind)

    Android MVVM UI 控件

    WPF 数据网格绑定(bind)工具提示在表格内容绑定(bind)刷新时闪烁

    c# - FolderPicker 无故立即关闭

    c# - 使用 LINQ 计算两个字符串之间的匹配字符

    c# - 如何在反序列化时覆盖默认集合

    c# - 转换为通用类型

    c# - 如何设置 AutoSuggestBox 中文本光标的位置?

    xaml - UWP 绑定(bind)到属性