【发布时间】:2014-01-02 05:49:38
【问题描述】:
我正在使用 Galasoft Mvvm Light 工具包,以 MVVM 模式为 windows phone 构建我的应用程序。我必须每个页面都有自己的视图模型。
当用户启动应用程序时,他可以选择新游戏并打开问题页面。这些页面都有一个视图模型,并且一切都使用视图模型定位器。当用户随后导航返回以再次在新游戏和问题之间进行选择时。视图模型/页面不会被删除。这意味着当用户第二次进入问题或新游戏时,视图模型的构造函数不会被调用,因此构造函数中的初始化不会运行,并且视图设置不正确。
我尝试过的解决方案
我尝试删除导航中的后台堆栈,例如新导航到新游戏或问题,应该启动一个新页面,从而调用构造函数。不工作。
在视图中使用加载的事件,并调用构造函数。不工作。
试图关注 How to reset all instances in IOC Container 但无法让它工作,可能只是我。
有没有人解决过这个问题,如果有,应该如何解决?
代码 在这里你可以找到一个例子。按问题,然后按一次那里的按钮,使用后键。并再次按问题。您会看到数字现在是 1,这很容易更改。但是当您再次按下按钮时会出现错误。突然出现两个弹出窗口。
那么设置视图模型的正确方法是什么。因为 newgame 的视图将在重新加载旧游戏时使用,仅使用其他值,以及当人们想要开始新游戏时。希望你明白:)
这个例子只是为了展示我每次返回视图模型页面时弹出窗口计数增加的问题。 https://www.dropbox.com/s/gjbz0l8rmsxqzrd/PhoneApp8.rar
ViewModel 定位器 我在我当前的项目中使用以下代码中的三个视图模型:
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Ioc;
using Microsoft.Practices.ServiceLocation;
namespace MVVMTestApp.ViewModel
{
public class ViewModelLocator
{
public ViewModelLocator()
{
//Holder styr på ViewModels
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
//Tilføj linje her for hver ViewModel
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<MainViewModelTest>();
SimpleIoc.Default.Register<MenuViewModel>();
}
//Tilføj metode som denne for hver ViewModel
public MainViewModel Map
{
get
{
return ServiceLocator.Current.GetInstance<MainViewModel>();
}
}
public MainViewModelTest Main
{
get
{
return ServiceLocator.Current.GetInstance<MainViewModelTest>();
}
}
public MenuViewModel Menu
{
get
{
return ServiceLocator.Current.GetInstance<MenuViewModel>();
}
}
public static void Cleanup()
{
// TODO Clear the ViewModels
}
}
我查看了上面引用的链接,重置了 IOC 容器中的所有实例。但是不确定键是如何工作的,以及如何确保在离开视图时调用清理函数。因为我不想同时清理所有视图模型。
导航和视图模型绑定
我将我的视图模型绑定到视图
DataContext="{Binding Source={StaticResource Locator},Path=Map}"
我使用 NavigationService 和后退按钮来回导航。从菜单到游戏:
NavigationService.Navigate(new Uri("/View/MainPage.xaml", UriKind.Relative));
在页面中
protected override void OnNavigatedTo(NavigationEventArgs e)
{
//e.Content = NavigationMode.New;
//e.NavigationMode = NavigationMode(
ViewModel.MainViewModel test = new ViewModel.MainViewModel();
GC.Collect();
base.OnNavigatedTo(e);
}
从游戏到菜单:
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
//e.NavigationMode = NavigationMode.
this.DataContext = null;
GC.Collect();
base.OnNavigatedFrom(e);
//test = null;
}
在菜单中我调用了垃圾收集器。可以看出,我打破了 MVVM 结构以适应问题。
【问题讨论】:
-
我认为如果您可以发布一个特定示例来演示该问题,您将获得更具体的答案。但总的来说,我认为视图模型的重点是跨页面加载持久化数据,因此您不应该对第二个页面视图保留第一个视图的数据感到惊讶。您可以通过将一些页面 init 从构造函数移出到从构造函数调用的函数以及从页面加载事件调用的函数中来处理此问题。
-
这正是我所做的。但是存在内存问题,因为在导航时没有清除视图模型。而且由于数据上下文设置为视图,因此我无法访问后面的视图模型。到目前为止,我必须做的是设置 datacontext = null,并调用 GC.collect()。但这不是一个很好的方法。我想知道正确的方法是什么。
-
请发布一个示例,展示您当前正在做什么(使用 cmets 展示您希望发生的事情)。当第二次加载 P1 时,给定页面 P1 的视图模型 V1 仍然在内存中,这是应该发生的。您是否在 P1.DataContext 中看到了其他视图模型?
-
@BobHy 我创建了一个小样本,我制作了一个 rar 文件并包含在文本中。
标签: c# mvvm windows-phone-8 ioc-container