正确处理用户控件及其子控件

时间:2012-09-17 12:59:24

标签: c# wpf dispose idisposable

我一直在寻找超过30分钟,但我根本无法弄清问题是什么。 我有一个TabControl,其项目将由用户关闭。由于每个TabItem都以某种方式连接到自定义控件,而且每个对象都使用了相当多的内存,因此我希望处理与此TabItem一起使用的所有对象。

为了更清楚,在这里为您节省了大量代码:

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

现在我设置相应tabitem的内容:

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

此外,我还有自定义对象,每个对象都包含一个网格,该网格作为内容添加到我的用户控件的滚动查看器中:

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;

现在,当用户想要关闭tabitem时,我还想摆脱myControl和每个对象myObject。 我试图通过IDisposable调用它们的Dispose方法但总是抛出NullReferenceException,我根本无法找出原因。

我应该提一下,每个myObject都在Dictionary<string, MyClass>范围内,但是在我调用dispose之前我从那里删除了对象。

2 个答案:

答案 0 :(得分: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
    }
}

答案 1 :(得分:0)

所以你要删除一个UI元素,然后尝试让模型更新,而不是:

为什么不将UI绑定到对象的ObservableCollection列表。然后删除你只需要从模型中的列表中删除(如果你愿意,可以配置)但是让UI完成它的工作并简单地重新选择对列表的更改。这就是WPF最好的方式。

阅读TabControl.ItemsSource,例如here.