0

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.

philkark
  • 2,417
  • 7
  • 38
  • 59

2 Answers2

1
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
    }
}
MrEdge
  • 74
  • 5
  • I create a new object: `IDisposable idispose = myObject[i] as IDisposable` And then call `idispose.Dispose();` – philkark Sep 17 '12 at 13:18
  • I think there lies your problem. You need to provide an implementation for IDispose. IDisposable idispose = myObject[i] as IDisposable will make idispose null since it is not an IDispose object. – MrEdge Sep 17 '12 at 13:21
  • If I understand your code cerrectly, you should implement the IDispose interface within your MyClass and do your custom disposing over there. Then your line of code above will work. – MrEdge Sep 17 '12 at 13:23
  • Oh I didn't realise that. I am quite new to C# and I thought I understood how to Dispose objects thanks to my books. Could you maybe provide a small code sample to show me how to implement IDispose correctly? – philkark Sep 17 '12 at 13:25
  • I changed my answer into a short sample, let me know if it works for you. Be sure to read msdn on this topic: http://msdn.microsoft.com/en-us/library/system.idisposable.aspx – MrEdge Sep 17 '12 at 13:34
  • It worked somehow, at least it solved the NullReference issue. However, I will need to read a bit more about this topic and also make sure all my objects are not used anymore, so no more exceptions are thrown. – philkark Sep 17 '12 at 21:35
  • (a bit late with my answer) Your nullref exception was caused by the fact that you tried to cast an object to an abject of type IDisposable. Since the object didn't have an implementation of that interface, the result of the cast is Null. – MrEdge Sep 24 '12 at 07:36
0

So you are removing a UI element and then trying to get the model to update, instead:

Why not bind the UI to a ObservableCollection list of your object. Then to remove you just need to remove from the list in the model (and dispose if you wish) but let the UI do it's job and simply relect the changes to the list. This is how WPF works best.

Read up on TabControl.ItemsSource Like here.

Community
  • 1
  • 1
weston
  • 54,145
  • 21
  • 145
  • 203
  • Thanks for the answer, I will try that, but I don't know if the problem does not lie within myObject somewhere. Afterall, it contains a lot of data, however, I am sure none of it is directly use when i try to dispose the object. – philkark Sep 17 '12 at 13:12