gpt4 book ai didi

c# - 一旦 frame 导航到另一个 Page 就销毁 ViewModel 和 Page 的实例

转载 作者:行者123 更新时间:2023-12-03 10:46:04 24 4
gpt4 key购买 nike

假设我有 3 页,即 Page1.xaml、Page2.xaml、Page3.xaml。

我有一个 window 和一个框架。 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"; }
}
}

我在上面代码中使用的接口(interface)是IModule,其声明如下:
public interface IModule
{
string ModuleFriendlyName { get; }
string ModuleName { get; }
}

当我的程序运行时,我想收集列表中所有页面的当前实例,然后我可以从另一个 ViewModel 访问任何 ViewModel 的当前实例。从中我可以得到另一个 ViewModel 中属性的当前值。但是实例不会自动添加到List中,所以我需要将它们添加到ViewModel的构造函数中的List中,并从ViewModel的Destructor中的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);
}
......
......
......
}

最佳答案

在 .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/

我不太确定为什么你需要在终结器中这样做,但这篇文章应该对你有所帮助:

Dispose Pattern

更新:

  • GC 永远不会调用终结器,因为 View 模型被添加到静态列表中,除非整个应用程序关闭。
  • 同样,在这里使用终结器来做你想做的事情是错误的。你无法控制它何时被调用。事实上,当你实现终结器时,它实际上与垃圾收集不同。您需要自己管理静态列表。
  • 关于c# - 一旦 frame 导航到另一个 Page 就销毁 ViewModel 和 Page 的实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25736608/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com