Issue
I have a wrappanel which is beeing used to apply tags to an image.
Tags can be added and removed:

The problem is the following: Upon removing an element, the memory is not released and also never garbage collected.
this is how I add the Control:
foreach (MetadataAttribute attribute in metadata.attributes)
{
this.Attributes_StackPanel.Children.Add(new Attribute(attribute));
}
this is how i removed the elements initially:
this.Attributes_StackPanel.Children.Clear();
What I tried
I found multiple resources and questions about the topic, but none of them seemed to work for me:
- name properties have to be set to null before clearing
- grids and stackpanels have to be cleared
- all references sould be cleared
- the element itself should be cleared
- name property of the parent should be cleared
I wandered through posts until I ended with an abomination like this:
parent:
/// <summary>
/// clears the attribute panel to prepare for new metadata to be loaded
/// </summary>
private void ClearAttributesPanel()
{
for(int i = this.Attributes_StackPanel.Children.Count-1; i > 0; i--)
{
Attribute attr = (Attribute)this.Attributes_StackPanel.Children[i];
attr.Delete();
attr = null;
}
}
xaml:
<UserControl x:Class="Minter_UI.Attribute"
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"
xmlns:local="clr-namespace:Minter_UI"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" Padding="0.1cm, 0.1cm, 0, 0">
<Grid x:Name="Main_Grid">
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="1cm"></ColumnDefinition>
<ColumnDefinition Width="0.5cm"></ColumnDefinition>
</Grid.ColumnDefinitions>
<StackPanel x:Name="Stack_Panel" Orientation="Vertical" Grid.Row="0">
<ComboBox x:Name="TraitType_ComboBox" IsEditable="True" Text="TraitType" SelectionChanged="TraitType_ComboBox_SelectionChanged"></ComboBox>
<ComboBox x:Name="Value_ComboBox" IsEditable="True" Text="Value"></ComboBox>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Label Content="MinValue" Grid.Column="0"></Label>
<Label Content="MaxValue" Grid.Column="1"></Label>
<TextBox x:Name="MinValue_TextBox" Grid.Row="1" Grid.Column="0"></TextBox>
<TextBox x:Name="MaxValue_TextBox" Grid.Row="1" Grid.Column="1"></TextBox>
</Grid>
</StackPanel>
<Button x:Name="Delete_Button" Content="X" Background="LightCoral" Grid.Column="1" Click="Delete_Button_Click"></Button>
</Grid>
</UserControl>
Attribute delete:
public void Delete()
{
// unregister events
this.TraitType_ComboBox.SelectionChanged -= this.TraitType_ComboBox_SelectionChanged;
this.Delete_Button.Click -= this.Delete_Button_Click;
// main grid
this.Main_Grid.Children.Clear();
this.Main_Grid = null;
// stack panel
this.Stack_Panel.Children.Clear();
this.Stack_Panel = null;
// textboxes
this.MinValue_TextBox.Text = null;
this.MinValue_TextBox = null;
this.MaxValue_TextBox.Text= null;
this.MaxValue_TextBox = null;
//comboboxes
this.TraitType_ComboBox.ItemsSource= null;
this.TraitType_ComboBox.SelectedItem= null;
this.TraitType_ComboBox.Text= null;
this.TraitType_ComboBox = null;
this.Value_ComboBox.ItemsSource = null;
this.Value_ComboBox.SelectedItem = null;
this.Value_ComboBox.Text = null;
this.Value_ComboBox = null;
// delete button
this.Delete_Button.Content = null;
this.Delete_Button = null;
// clear all x:name properties
this.UnregisterName("Stack_Panel");
this.UnregisterName("MinValue_TextBox");
this.UnregisterName("MaxValue_TextBox");
this.UnregisterName("TraitType_ComboBox");
this.UnregisterName("Value_ComboBox");
this.UnregisterName("Main_Grid");
this.UnregisterName("Delete_Button");
// remove self from parent
((Panel)this.Parent).Children.Remove(this);
}
Still, this doesnt work. I can find thousands of references to the comboboxes and textpanels as well as hashtables in heap after enough reloads. After a while, the garbage collector goes crazy but never actually clears any elements.
I dont kow if this is the way to do it but it works:
This will not neglect the memory leak from manually pressing the delete button of the control but this will likely be neglible. Whenever the information is reloaded however, elements get recycled instead of destroyed and created freshly.
This might have some implications if you do not make sure all fields and values are properly cleared. For example you might find values from the previus property.