假设我有3个页面,即Page1.xaml,Page2.xaml,Page3.xaml。
我有一个窗口和一个框架。 Frame的声明如下:
<Frame Source="{Binding SourcePage}" NavigationUIVisibility="Hidden" />
我正在做一些工作,比如在构造函数中增加全局计数器变量,并在每个页面的析构函数中减少全局计数器。
让我们将此全局计数器命名为x。因此代码应如下所示:
public int x = 0;
的Page1.xaml (与Page1关联的ViewModel是ViewModel1)
public ViewModel1()
{
x++;
}
~ViewModel1()
{
x--;
}
类似地:
Page2.xaml (与Page2关联的ViewModel是ViewModel2)
public ViewModel2()
{
x++;
}
~ViewModel2()
{
x--;
}
Page3.xaml (与Page3关联的ViewModel是ViewModel3)
public ViewModel3()
{
x++;
}
~ViewModel3()
{
x--;
}
现在,我在运行时更改了帧的来源。
最初,帧的来源是Page1.xaml。因此,调用ViewModel1的构造函数。所以x的值变为1。
然后我在运行时使用按钮帮助改变帧的来源到Page2.xaml。因此,调用ViewModel2的构造函数。因此,x的值变为2.现在,我希望立即调用ViewModel1的析构函数。这样x应该再次变为1。但是从不调用ViewModel1的析构函数。
然后我再次在运行时使用按钮帮助改变帧的来源到Page3.xaml。因此,调用ViewModel3的构造函数。因此,x的值变为3.现在,我希望立即调用ViewModel2的析构函数。这样x应该再次成为2。但是从不调用ViewModel2的析构函数。
然后我再次在运行时使用按钮帮助改变帧的来源到Page1.xaml。因此,调用ViewModel1的构造函数。因此,x的值变为4.现在,我希望立即调用ViewModel3的析构函数。这样x应该再次变为3。但是从不调用ViewModel3的析构函数。
当我关闭程序时,会调用这些ViewModel的析构函数。我不想要这种行为。我总是想在框架导航到另一个页面时立即销毁ViewModel和Page的实例。
非常感谢任何帮助。
更新
让我在这里澄清一下这个问题。
这里的要点是我想从另一个ViewModel中获取一个ViewModel中属性的当前值。
我有一个SessionViewModel如下:
public sealed class SessionViewModel : ViewModelBase, IModule
{
private static readonly SessionViewModel instance = new SessionViewModel();
public static SessionViewModel Instance
{
get
{
return instance;
}
}
private List<IModule> modulesOpen;
public List<IModule> ModulesOpen
{
get
{
return modulesOpen;
}
set
{
modulesOpen = value;
NotifyPropertyChanged("ModulesOpen");
}
}
public static IModule GetModuleInstance(string moduleName, string finalName)
{
IModule moduleToOpen = null;
if (Instance.ModulesOpen != null)
{
moduleToOpen = Instance.ModulesOpen.SingleOrDefault(mod => mod.ModuleName == moduleName);
}
else
{
Instance.ModulesOpen = new List<IModule>();
}
if (moduleToOpen != null) return moduleToOpen;
Type module = Type.GetType(finalName);
moduleToOpen = (IModule)Activator.CreateInstance(module);
Instance.ModulesOpen.Add(moduleToOpen);
return moduleToOpen;
}
public string ModuleFriendlyName
{
get { return "SessionViewModel"; }
}
public string ModuleName
{
get { return "Session"; }
}
}
上面代码中使用的接口是IModule,其声明如下:
public interface IModule
{
string ModuleFriendlyName { get; }
string ModuleName { get; }
}
当我的程序运行时,我想收集列表中所有页面的当前实例,然后我可以从另一个ViewModel访问任何ViewModel的当前实例。从那里我可以在另一个ViewModel中获取属性的当前值。但实例不会自动添加到List中,因此我需要将它们添加到ViewModel的构造函数中的List中,并将它们从ViewModel的析构函数中的List中删除。
让我们看看MainWindowViewModel的代码:
public class MainWindowViewModel : IModule, ViewModelBase
{
public MainWindowViewModel() //Constructor
{
SessionViewModel.Instance.ModulesOpen = new List<IModule>();
SessionViewModel.Instance.ModulesOpen.Add((IModule)this);
}
~MainWindowViewModel()
{
SessionViewModel.Instance.ModulesOpen.Remove((IModule)this);
}
..
..
..
}
在ViewModel1.cs
中public class ViewModel1 : IModule, ViewModelBase
{
public ViewModel1()
{
SessionViewModel.Instance.ModulesOpen.Add((IModule)this);
}
~ViewModel1()
{
SessionViewModel.Instance.ModulesOpen.Remove((IModule)this);
}
......
......
......
}
在ViewModel2.cs
中public class ViewModel2 : IModule, ViewModelBase
{
public ViewModel2()
{
SessionViewModel.Instance.ModulesOpen.Add((IModule)this);
}
~ViewModel2()
{
SessionViewModel.Instance.ModulesOpen.Remove((IModule)this);
}
......
......
......
}
在ViewModel3.cs
中public class ViewModel3 : IModule, ViewModelBase
{
public ViewModel3()
{
SessionViewModel.Instance.ModulesOpen.Add((IModule)this);
}
~ViewModel3()
{
SessionViewModel.Instance.ModulesOpen.Remove((IModule)this);
}
......
......
......
}
答案 0 :(得分:0)
在.Net托管应用程序中,内存释放由垃圾收集器(GC)管理。 GC根据一些复杂的规则决定何时调用终结器。所以这就是它做了你所期望的事情的原因。这些文章将有助于理解.Net中的垃圾收集
http://msdn.microsoft.com/en-us/library/0xy59wtx(v=vs.110).aspx http://joeduffyblog.com/2005/12/27/never-write-a-finalizer-again-well-almost-never/
我不确定为什么你需要在终结器中这样做,但这篇文章对你有帮助:
更新: