Search code examples
c#wpfdisposeidisposable

Correctly disposing user control and its children


I have been looking for over 30 minutes now, but I simply cannot figure out what the problem is. I have a TabControl and its items are to be closed by the user. Since each TabItem is in a way connected to a custom control and several objects that each use quite a lot of memory, I would like to dispose all objects that are used together with this TabItem.

To make it clearer and save you a lot of code here the simplified situation:

<UserControl x:Class="myProject.GridFour"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
        <ScrollViewer Height="Auto" Margin="0" Name="scrollViewer11" Width="Auto" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"></ScrollViewer>
        <ScrollViewer Grid.Column="1" Height="Auto" Name="scrollViewer12" Width="Auto"  Margin="0" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"></ScrollViewer>
        <ScrollViewer Grid.Row="1"> Height="Auto" Name="scrollViewer21" Width="Auto" Margin="0" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"></ScrollViewer>
        <ScrollViewer Height="Auto" Name="scrollViewer22" Width="Auto" Grid.Column="1" Margin="0" Grid.Row="1" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"></ScrollViewer>
    </Grid>
</UserControl>

Now I set the content of the corresponding tabitem:

GridFour myControl = new GridFour();
myTabItem.Content = myControl;

Also I have custom objects that each contain a grid, which is added as content to the scrollviewers of my user control:

class MyClass
{
    internal Grid _grid = new Grid();
    internal Image _image = new Image() {Width = Double.NaN, Height = Double.NaN HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, Stretch = Stretch.Fill};
    //... a lot of variables, data, images and methods...
}

MyClass[] myObject = new MyClass[4];

for(int i = 0; i < 4; i++)
{
    myObject[i] = new MyClass();
    myObject[i]._grid.Children.Add(_image); //that actually happens when I initialise the object, it is just to show how everything is connected
}

myControl.scrollViewer11.Content = myObject[0]._grid;
myControl.scrollViewer12.Content = myObject[1]._grid;
myControl.scrollViewer21.Content = myObject[2]._grid;
myControl.scrollViewer22.Content = myObject[3]._grid;

Now when the user would like to close the tabitem obviously I would also like to get rid of myControl and of every single object myObject. I tried to call the Dispose method on them via IDisposable but that always throws a NullReferenceException and I simply cannot figure out why.

I should maybe mention that every single myObject is within a Dictionary<string, MyClass> but I remove the object from there before I call dispose.


Solution

  • class MyClass : IDisposable
    { 
        internal Grid _grid = new Grid(); 
        internal Image _image = new Image() {Width = Double.NaN, Height = Double.NaN HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, Stretch = Stretch.Fill}; 
        //... a lot of variables, data, images and methods... 
    
        public void Dispose()
        {
            // your custom disposing 
            _image = null; //or something like that
        }
    }