1

我有一个奇怪的行为,我认为这与绑定有关。基本上,我怀疑我的控件在 ViewModel 上的绑定会创建从 PropertyChanged 事件到控件的强引用。因此 ViewModel 始终保持对控件的引用。因此,即使我完成了控件,它们也始终保存在内存中。这将一直存在,直到我销毁我的 ViewModel,但在我的情况下,我有一个 ViewModel 来处理所有事情。有没有办法可以解除绑定创建的事件?

这是对我的问题的更详细解释,也是使我产生上述信念的原因:

我有一个视图模型:

public ViewModel()
{
    InitializeCommands();
}

public ICommand OpenPropertiesCommand { get; set; }

private void InitializeCommands()
{
    OpenPropertiesCommand = new DelegateCommand((o) =>
    {
        OpenProperties(o as ContentControl);
    });
}

private void OpenProperties(ContentControl propertiesWindowOwner)
{
    JobProperties jp = new JobProperties(this);
    jp.WindowStartupLocation = Telerik.Windows.Controls.WindowStartupLocation.CenterOwner;
    jp.Owner = propertiesWindowOwner;
    jp.ShowDialog();
}

private Job selectedJob;
public Job SelectedJob
{
    get
    {
        return selectedJob;
    }
    set
    {
        selectedJob = value;
        RaisePropertyChanged("SelectedJob");
    }
}

这个 ViewModel 由我的主控件使用。在这个控件上,我有一个 GridView,其中每一行都是一个“作业”。您可以编辑作业的属性,这将打开一个 RadWindow 控件,让您编辑每个作业的属性。

我的 PropertyEdit 控件是一个 RadWindow,它使用与 DataContext 相同的 ViewModel。它的所有组件都绑定在 SelectedJob.something 上,其中 something 是 Job 的属性。

如果我打开 Job #1 属性。创建一个 PropertyEdit 控件并建立绑定。对于每个绑定,我的属性 SelectedJob.something 应该被访问一次。如果我关闭 PropertyEdit 控件并再次打开 Job #1 属性。又创建了一个 PropertyEdit 控件并建立了绑定。现在,如果我关闭这个并选择另一个作业,则会在 selectedJob 上调用 PropertyChanged 事件,并且每次绑定都会调用我的绑定两次。实际上,第一个 PropertyEdit 控件绑定被激活,第二个 PropertyEdit 绑定也被激活。现在,如果我打开 Job #1 属性 100 次,当我选择 Job #2 时,每个绑定都会被查询 100 次。因此,我怀疑内存泄漏,绑定将我的 PropertyEdit 控件保留在内存中,因为它们引用了所有这些。在我销毁我的 ViewModel 之前,这些引用将被保留,但在我的情况下,它是我的主应用程序的 ViewModel,并且永远不会被销毁。我怎样才能防止这种情况发生?有没有办法手动取消注册绑定的事件?

谢谢你。

4

1 回答 1

0

我已经解决了这个问题。问题不在于绑定,但似乎 Window 的 Owner 属性以某种方式阻止了窗口被垃圾收集。

通过注释掉这一行:

jp.Owner = propertiesWindowOwner;

我解决了这个问题。我不确定这是为什么。我怀疑设置窗口的所有者具有将窗口设置为propertiesWindowOwner的子级的副作用。因此,在我销毁 propertiesWindowOwner 之前,它会保留对我的窗口的引用,即使在关闭它之后也是如此。

我有点困惑为什么会发生这种情况,以及在这样做时我需要做什么来不泄漏内存。如果有人知道,请对此发表评论。

于 2012-11-14T19:31:02.400 回答