簡體   English   中英

處置通過ContentPresenter加載的UserControl

[英]Disposing a UserControl loaded via ContentPresenter

我的mainView(窗口)上有以下代碼

<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>

因此刪除綁定,再次啟動我的啟動應用程序,單擊加載按鈕,然后單擊卸載按鈕兩次,我得到了以下信息:

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並不是一種選擇。

好的,我要結束這件事,因為實際上清理是按照正確的方式進行的,但是似乎GarbageCollector確實花了一些時間來考慮在win8.1機器上進行清理。 在“卸載”按鈕上單擊約10-15次后,將進行清理。 在win7機器上,清除總是在第二次單擊時進行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM