WPF 正确处理视图和视图模型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13175280/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 06:01:35  来源:igfitidea点击:

WPF disposing of view and viewmodel correctly

c#wpfmvvm

提问by MJM

I've written an Outlook add-in (OL2010). It has a menu on the ribbon bar with various icons that open new windows that do stuff (hope that's not too in-depth ;)). An example of one of the icon Clickhandlers is below.

我编写了一个 Outlook 加载项 (OL2010)。它在功能区栏上有一个带有各种图标的菜单,这些图标可以打开执行某些操作的新窗口(希望不会太深入;))。Click下面是图标处理程序之一的示例。

public void OnViewMyTracksClick(Office.IRibbonControl control)
{
    try {
    MyTracksViewModel viewModel = new MyTracksViewModel();
    MyTracksView view = new MyTracksView();
    view.DataContext = viewModel;
    view.Show();
    }
    catch (Exception ex)
    {
        Log.Error("xxxxx", "Error on button click: " + ex.Message + Environment.NewLine + ex.InnerException);
    }
}

In Outlook, if I click the button to open this view, I see the memory usage of Outlook.exeincrease by 10mb (the window and it's accompanying data). When I close the view, none of that memory is reclaimed. If I click the button again, another 10mb is added, and again, none is released when I close the view.

在 Outlook 中,如果我单击按钮打开此视图,我会看到内存使用量Outlook.exe增加了 10mb(窗口及其附带的数据)。当我关闭视图时,没有任何内存被回收。如果我再次单击该按钮,则会添加另一个 10mb,并且在我关闭视图时再次没有释放任何内容。

I thought that this is because I'm creating a new viewmodel everytime, so I added some code to check if it was already instantiated (the view and viewmodel are now registered at the class level, rather that within the method, so that I don't create a new one each time) - _allTracksVMis an instantiation of AllTracksViewModel. _allTracksVis the view.

我认为这是因为我每次都在创建一个新的视图模型,所以我添加了一些代码来检查它是否已经被实例化(视图和视图模型现在是在类级别注册的,而不是在方法中,所以我不't 每次都创建一个新的) -_allTracksVMAllTracksViewModel. _allTracksV是视图。

public void OnViewAllTracksClick(Office.IRibbonControl control)
{
    try {
        if (_allTracksVM == null)
        {
            _allTracksVM = new AllTracksViewModel();

        }
        _allTracksV = new AllTracksView();
        _allTracksV.DataContext = _allTracksVM;
        _allTracksV.Show();
    }
    catch (Exception ex)
    {
        Log.Error("xxxxx", "Error on button click: " + ex.Message + Environment.NewLine + ex.InnerException);
    }
}

This didn't seem to make any difference. I then added an EventHandlerthat would fire when the view was closed:

这似乎没有任何区别。然后我添加了一个EventHandler在视图关闭时会触发的:

_allTracksV.Closing += new System.ComponentModel.CancelEventHandler(this.view_RequestClose);

And this set both the objects to null (you can probably tell i'm grabbing at straws at this point):

这将两个对象都设置为空(您可能会说我此时正在抓住稻草):

void view_RequestClose(object sender, EventArgs e)
{
    _allTracksVM = null;
    _allTracksV = null;
}

The memory remains allocated. How can I dispose of the objects correctly (or perhaps I should be instantiating them differently), so that they don't consume another chunk of memory each time they are opened?

内存保持分配。我如何正确处理对象(或者我可能应该以不同的方式实例化它们),以便它们每次打开时都不会消耗另一块内存?

Thanks

谢谢

Mick

米克

采纳答案by MrEdge

Checking the VM for Null was a good idea but by setting it to null in the close handler, it is rendered useless :) You could try to make the view a field in the containing class rather than a local variable. That way you don't need to create a new view each time.

检查 VM 是否为 Null 是一个好主意,但通过在关闭处理程序中将其设置为 null,它变得无用:) 您可以尝试使视图成为包含类中的字段而不是局部变量。这样您就不需要每次都创建一个新视图。

As for the memory usage, it seems to me that you're doing it right. Since the GC only collects when necessary, it will take some time until the memoryusage declines.

至于内存使用,在我看来你做得对。由于 GC 仅在必要时收集,因此内存使用率下降需要一些时间。