[英]clearing child controls from wrappanel does not clear memory and references
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.问题如下:删除元素后,memory 不会被释放,也不会被垃圾回收。
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();
I found multiple resources and questions about the topic, but none of them seemed to work for me:我找到了有关该主题的多个资源和问题,但似乎没有一个对我有用:
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: 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:我不知道这是不是这样做的方法,但它有效:
public void SetAttribute(MetadataAttribute attribute)
{
// you need to extend the function, its just an example
this.TraitType_ComboBox.Text = attribute.trait_type.ToString();
this.Value_ComboBox.Text = attribute.@value.ToString();
this.MinValue_TextBox.Text = attribute.min_value.ToString();
this.MaxValue_TextBox.Text = attribute.max_value.ToString();
}
Queue<Attribute> AttributeReuseElements = new Queue<Attribute>();
private void ClearAttributesPanel()
{
for(int i = this.Attributes_StackPanel.Children.Count-1; i > 0; i--)
{
AttributeReuseElements.Enqueue((Attribute)this.Attributes_StackPanel.Children[i]);
this.Attributes_StackPanel.Children.RemoveAt(i);
}
}
foreach (MetadataAttribute attribute in CollectionInformation.Information.LikelyAttributes)
{
if (AttributeReuseElements.Count > 0)
{
Attribute attr = AttributeReuseElements.Dequeue();
attr.SetAttribute(attribute);
this.Attributes_StackPanel.Children.Add(attr);
}
else
{
this.Attributes_StackPanel.Children.Add(new Attribute(attribute));
}
}
This will not neglect the memory leak from manually pressing the delete button of the control but this will likely be neglible.这不会忽略手动按下控件的删除按钮导致的 memory 泄漏,但这可能可以忽略不计。 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.
例如,您可能会从 previus 属性中找到值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.