rkmax
rkmax

Reputation: 18133

Customizing TabItem : Closeable Tab and release memory on Close

Customizing TabItem

I have a TabControl bound to my ViewModel i also want to remove tabs but i cant see the canges the tabitems see default without changes

    <TabControl
        Margin="5 5 5 0"
        Grid.Row="1"
        ItemsSource="{Binding Path=ListTabItem}"
        SelectedIndex="{Binding Path=CurrentTabItemIndex}"
        x:Name="Workspace" Background="White">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="SelectionChanged">
                <cmd:EventToCommand
                Command="{Binding ChangeTabCommand}"
                CommandParameter="{Binding SelectedItem, ElementName=Workspace}"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
        <!--Here is my tabHeader-->
        <TabControl.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Header}" />                        
                    <Button Content="X" Command={Binding CloseTabCommand}
                      CommandParameter="{Binding SelectedItem, ElementName=Workspace}"/>
                </StackPanel>
            </DataTemplate>
        </TabControl.ItemTemplate>            
    </TabControl>

EDIT:

I get a working style, but i have the problem when close a tab dont release the memory:

    <Style x:Key="HeaderTabItem" TargetType="TabItem">
        <Setter Property="HeaderTemplate">
            <Setter.Value>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="Auto" />
                        </Grid.ColumnDefinitions>
                        <Button                                
                            Width="20"
                            Height="20"
                            Margin="-3 0 5 0"
                            Padding="2"
                            HorizontalAlignment="Left"
                            VerticalAlignment="Center"
                            BorderBrush="{x:Null}" Background="{x:Null}" Foreground="{x:Null}"
                            DataContext="{Binding DataContext, ElementName=Workspace}"
                            Command="{Binding Path=CloseTabCommand}"
                            CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=TabItem, AncestorLevel=1}}" Content="X"/>
                        <ContentControl
                            Grid.Column="1" 
                            VerticalAlignment="Center"
                            HorizontalAlignment="Left"
                            Content="{Binding Path=Header, RelativeSource={RelativeSource FindAncestor, AncestorType=TabItem, AncestorLevel=1}}" />
                    </Grid>
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>

in my ViewModel

    CloseTabCommand = new RelayCommand<TabItem>(tab =>
    {
        if (null == tab) return;
        ListTabItem.Remove(tab);
    },
    tab =>
    {
        return ListTabItem.IndexOf(tab) == CurrentTabItemIndex;
    });

any ideas?

Upvotes: 0

Views: 1166

Answers (1)

Locke
Locke

Reputation: 1165

WPF controls tend to not dispose themselves appropriately unless their DataContext has been cleared (which seems like kind of a hack). Try this:

CloseTabCommand = new RelayCommand<TabItem>(tab =>
{
    if (null == tab) return;

    tab.DataContext = null;

    ListTabItem.Remove(tab);
},
tab =>
{
    return ListTabItem.IndexOf(tab) == CurrentTabItemIndex;
});

Also, keep in mind that you may not see the memory released immediately. Due to how Garbage Collection works in .NET, your application may need to wait/other events for Garbage Collection to actually occur and memory to be cleared.

If you really want to, you can call GC.Collect(), but I would do this only if you are unconvinced that the memory is being freed and I would only put it in to debug and ensure that the objects are being freed. After you confirm, remove it and allow the Garbage Collector to do its job.

Upvotes: 1

Related Questions