【问题标题】:Using new ViewModel each time I open a page每次打开页面时都使用新的 ViewModel
【发布时间】:2016-12-09 15:05:55
【问题描述】:

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

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

  • 打开详细信息页面时可以在瞬间看到以前的数据

  • 我需要在页面打开时将某些属性设置为特定值,但由于 VM 被重复使用,它保留了之前详细信息中的所有值,这弄乱了我的逻辑。

这个 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);
    }
} 

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

【问题讨论】:

  • 我在使用 NavigationCacheMode 时遇到了同样的问题。我删除旧数据并在OnNavigatedTo 中初始化页面。只需在加载新数据之前删除DataContext = null;,完成后重新附加即可。
  • 您能否更具体地说明如何在我的代码中执行此操作?谢谢。
  • 我不知道您如何将您的页面绑定到您的视图模型。如果您将 DataContext 设置为您的 Viewmodel,请移除绑定 DataContext = null; 在您的 ViewModel 中设置新数据并使用 DataContext = mangaDetailViewModel 重新附加它。在您的 DetailPage OnNavigatedTo 中执行此操作。
  • 我在视图中绑定它。我不认为我可以在那里做到这一点。但实际上,解决方案要简单得多(或者至少看起来如此)。我刚刚禁用了 NavigationCacheMode(将其设置为禁用)。我假设这种捕捉不是 UWP 原生的,而是 Template10 的功能?
  • NavigationCacheMode 是原生 UWP,应该默认禁用。不确定 Template10。

标签: c# mvvm uwp template10


【解决方案1】:

另一个解决方案是使用 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() 和您包含的其他导航覆盖。

祝你好运。

【讨论】:

  • 糟糕,我的解决方案实际上与您的要求相反。
【解决方案2】:

虽然 Template10 文档声明 NavigationCacheMode 默认禁用,但在它的示例模板中并非如此(截至撰写本文时)。这是在查看 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; 
        }
    }
}

现在,每次访问此页面时都会创建新的 ViewModel。

【讨论】:

    猜你喜欢
    • 2019-08-06
    • 2019-05-22
    • 1970-01-01
    • 2011-07-30
    • 2017-10-30
    • 2021-05-30
    • 1970-01-01
    • 1970-01-01
    • 2017-08-04
    相关资源
    最近更新 更多