WPF选项卡窗口中的内存泄漏

时间:2016-02-03 12:38:23

标签: c# wpf mvvm

我有WPF .Net 4项目,其中存在内存泄漏问题。经过调查我发现窗口中的问题与标签。

选项卡中的数据显示为View,有两种类型的视图(Type1View和Type2View)。将所选项从type1更改为type2(或相反)后,将调用构造函数。我认为存在问题的根源,因为之后内存消耗增加,但是在关闭选项卡后不会清除。我试图使用GC.Collect,但它没有帮助。你能告诉我,如何解决这个问题?

下面的标签窗口实现(没有标签关闭)的测试项目代码:

标签窗口的XAML:

<Window x:Class="TestApp.Views.TypesViewTabWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="TypesViewTabWindow" Height="294" Width="520">

    <Window.Resources>
        <ResourceDictionary Source="ResourceDictionaries\TabDictionary.xaml" />
    </Window.Resources>

    <TabControl IsSynchronizedWithCurrentItem="True" 
                ItemsSource="{Binding Workspaces}"
                Margin="4" 
                HorizontalContentAlignment="Stretch"
                Background="White" >
        <TabControl.ItemContainerStyle>
            <Style TargetType="{x:Type TabItem}">
                <Setter Property="Width" Value="{Binding ElementName=ContentSite, Path=ActualWidth}" />
                <Setter Property="IsSelected" Value="{Binding IsActive}" />
                <Setter Property="Template" Value="{StaticResource TabItemStyle}" />
            </Style>
        </TabControl.ItemContainerStyle>
    </TabControl>
</Window>

标签窗口的资源字典:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ViewModel="clr-namespace:TestApp.ViewModels" xmlns:View="clr-namespace:TestApp.Views"
                xmlns:gif="http://wpfanimatedgif.codeplex.com">

<DataTemplate DataType="{x:Type ViewModel:Type1AgregateViewModel}" x:Shared="False">
    <View:Type1View />
</DataTemplate>

<DataTemplate DataType="{x:Type ViewModel:Type2AgregateViewModel}" x:Shared="False">
    <View:Type2View />
</DataTemplate>

<ControlTemplate x:Key="TabItemStyle" TargetType="{x:Type TabItem}">
    <Grid x:Name="gr">
        <Border Name="Border" Background="#F0F0F0" BorderBrush="LightGray" BorderThickness="1,1,1,0" CornerRadius="4,4,0,0" Margin="-2,0,3,0" SnapsToDevicePixels="True" >

            <Grid Margin="10,0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="15" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="15" />
                </Grid.ColumnDefinitions>

                <TextBlock ToolTip="{Binding Path=Name}" MaxWidth="135" x:Name="TextBlock" Margin="10,5,10,5" FontSize="15" Foreground="DarkGray" Grid.Column="1"
                           Text="{Binding Path=Name}" HorizontalAlignment="Center" VerticalAlignment="Center" TextTrimming="WordEllipsis"/>
            </Grid>
        </Border>
    </Grid>
</ControlTemplate>

标签窗口的ViewModel:

public class TypesViewTabViewModel : ViewModelBase
{
    private readonly Dispatcher _currentDispatcher;

    public TypesViewTabViewModel()
    {
        _currentDispatcher = Dispatcher.CurrentDispatcher;
    }

    /// <summary>
    /// workspace for the tabs
    /// </summary>
    private ObservableCollection<AbstractWorkspaceViewModel> _workspaces;

    /// <summary>
    /// workspace for the tabs
    /// </summary>
    public ObservableCollection<AbstractWorkspaceViewModel> Workspaces
    {
        get
        {
            if (_workspaces == null)
            {
                _workspaces = new ObservableCollection<AbstractWorkspaceViewModel>();
            }
            return _workspaces;
        }
    }

    public void AddNewWorkspace(AbstractWorkspaceViewModel newWorkspace)
    {
        if (newWorkspace == null) throw new ArgumentNullException("newWorkspace");

        var viewModel = newWorkspace as IIdentifier;

        try
        {
            AbstractWorkspaceViewModel workspace;
            if (viewModel != null)
            {
                var taskAgregateViewModels = Workspaces.OfType<IIdentifier>().ToList();
                workspace = (AbstractWorkspaceViewModel)taskAgregateViewModels.Where(t => ((t.Id == viewModel.Id) && (t.GetType() == viewModel.GetType()))).FirstOrDefault();
                if (workspace == null)
                {
                    workspace = (AbstractWorkspaceViewModel) newWorkspace.Clone();
                    Workspaces.Add(workspace);
                }
            }
            else
            {

                workspace = (AbstractWorkspaceViewModel)newWorkspace.Clone();

                var indexWorkspace = Workspaces.IndexOf(workspace);

                if (indexWorkspace < 0) Workspaces.Add(workspace);
            }

            SetActiveWorkspace(workspace);
        }
        catch (Exception ex)
        {
            throw new Exception();
        }
    }

    private void SetActiveWorkspace(AbstractWorkspaceViewModel workspace)
    {
        if (workspace == null) throw new ArgumentNullException("workspace");

        var collectionView = CollectionViewSource.GetDefaultView(Workspaces);

        if (collectionView == null) return;

        collectionView.MoveCurrentTo(workspace);

        collectionView.Refresh();
    }
}

其他视图和视图模型仅包含构造函数和一些字段。完整示例项目:https://www.dropbox.com/s/y2awoul21wekphw/TestApp.zip?dl=0

0 个答案:

没有答案