处置通过ContentPresenter

时间:2015-08-28 09:14:08

标签: c# wpf xaml user-controls

我在mainView(Window)上有以下代码

<StackPanel>
    <Button Click="OnLoadChildView">Load</Button>
    <Button Click="OnUnloadChildView">UnLoad</Button>
    <ContentPresenter Content="{Binding ChildViewModel}"/>
</StackPanel>

和我的ChildView(UserControl)上的代码

<StackPanel>
    <local:MyListBox ItemsSource="{Binding Items}">
    </local:MyListBox>
</StackPanel>

这是MainView的代码

public MainView()
{
    InitializeComponent();

    MainViewModel vm = new MainViewModel();
    this.DataContext = vm;
}

public MainViewModel Model { get { return this.DataContext as MainViewModel; } }

private void OnLoadChildView(object sender, System.Windows.RoutedEventArgs e)
{
    this.Model.ChildViewModel = new ChildViewModel();
}

private void OnUnloadChildView(object sender, System.Windows.RoutedEventArgs e)
{
    this.Model.ChildViewModel = null;
    GC.Collect();
    GC.WaitForPendingFinalizers();
    GC.Collect();
}

这里是我的其他代码:

public class MyListBox : ListBox
{
    public MyListBox() { Debug.WriteLine("Created instance of MyListBox:" + this.GetHashCode()); }
    ~MyListBox() { Debug.WriteLine("destroyed instance of MyListBox:" + this.GetHashCode()); }
}

public class ViewModelBase : INotifyPropertyChanged
{
    private PropertyChangedEventHandler _propertyChanged;

    public event PropertyChangedEventHandler PropertyChanged
    {
        add
        {
            _propertyChanged += value;
        }
        remove
        {
            _propertyChanged -= value;
        }
    }

    protected virtual void OnPropertyChanged(string property)
    {
        if (_propertyChanged != null)
        {
            _propertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }
}

public class MainViewModel : ViewModelBase
{
    private ChildViewModel _ChildViewModel;
    public ChildViewModel ChildViewModel
    {
        get { return _ChildViewModel; }
        set
        {
            if (_ChildViewModel != value)
            {
                _ChildViewModel = value;
                OnPropertyChanged(nameof(ChildViewModel));
            }
        }
    }
}

public class ChildViewModel : ViewModelBase
{
    public ChildViewModel()
    {
        Debug.WriteLine("Created instance of ChildViewModel:" + this.GetHashCode());
        this.Items = new List<string>(new string[] { "ABC", "DEF" });
    }

    ~ChildViewModel()
    {
        this.Items = null;
        Debug.WriteLine("destroyed instance of ChildViewModel:" + this.GetHashCode());
    }

    private IEnumerable<string> _Items;
    public IEnumerable<string> Items
    {
        get { return _Items; }
        set
        {
            if (_Items != value)
            {
                _Items = value;
                OnPropertyChanged(nameof(Items));
            }
        }
    }
}

我使用应用资源来查看视图:

 <Application.Resources>
        <DataTemplate DataType="{x:Type vm:ChildViewModel}">
            <vw:ChildView/>
        </DataTemplate>
    </Application.Resources>

当我启动应用程序并单击加载按钮,然后几次卸载按钮时,我得到了这个输出:

Created instance of ChildViewModel:2670961
Created instance of ChildView:2080614
Created instance of MyListBox:33397791
destroyed instance of ChildViewModel:2670961

当我将ChildView的XAML更改为:

   <StackPanel>
        <local:MyListBox>
        </local:MyListBox>
    </StackPanel>

所以删除Binding,再次启动我的应用程序,单击加载按钮然后卸载按钮几次我得到这个:

Created instance of ChildViewModel:30767036
Created instance of ChildView:50297887
Created instance of MyListBox:5453341
destroyed instance of MyListBox:5453341
destroyed instance of ChildViewModel:30767036
Destroyed instance of ChildView:50297887

所以看起来我真的无法摆脱WPF的NotifyPropertyChangedEventHandler,所以我的列表框和我的视图不会被处理掉。我怎样才能做到这一点?因为我认为它正在清除,所以删除Binding不是一种选择。

1 个答案:

答案 0 :(得分:0)

好的我正在关闭它,因为实际上清理是以正确的方式构建的,但似乎GarbageCollector正在花费一些时间来考虑在win8.1机器上进行清理。在卸载按钮上大约单击10-15次后,将进行清理。在win7机器上,清理始终在第二次单击时发生。