Reputation: 18133
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>
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;
});
Upvotes: 0
Views: 1166
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