我有一个Snapshot
对象的ObservableCollection,绑定到ListBox的ItemsSource。
如果将新的Snapshot
对象推入集合中,并且集合已包含3个元素,则删除最后一个Snapshot
对象。但是,GC永远不会收集已删除的对象。为了验证这一点,我从集合中删除了一个Object并使用YourKit Profiler对我的应用程序进行了分析后调用了GC.Collect()
。创建6个Snapshot
对象后,YourKit Profiler创建了一个内存快照。所有6个Snapshot
对象仍然存在,尽管Collection只引用了3个。其他3个由System.Windows.EffectiveValueEntry引用。
如果集合未绑定到ListBox的ItemsSource,则会按预期收集Snapshot
个对象。
如何摆脱System.Windows.EffectiveValueEntry的引用?
public class Snapshot
{
public BitmapImage PreviewImage { get; set; } // Freezed BitmapImage
public string Path { get; set; }
public string Name
{
get
{
return System.IO.Path.GetFileNameWithoutExtension(Path);
}
}
}
XAML:
<ListBox ItemsSource="{Binding Path=LastCapturedPictures}"
SelectedItem="{Binding Path=SelectedCapturedPicture}" HorizontalAlignment="Stretch"
Margin="0,2,0,0" Grid.Column="1" Grid.Row="3">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical" VerticalAlignment="Center"
HorizontalAlignment="Left"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="5,0,5,0">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Image Source="{Binding Path=PreviewImage}" Width="130" Height="100"
Margin="0,0,0,2" Grid.Row="0" HorizontalAlignment="Left">
<Image.BitmapEffect>
<DropShadowBitmapEffect/>
</Image.BitmapEffect>
</Image>
<TextBlock Text="{Binding Path=Name}" Margin="0,2,0,0" Grid.Row="1"
TextAlignment="Left"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
答案 0 :(得分:4)
这可能已经很晚了,但我认为你的问题不在于EffectiveValueEntry,而在于你的Snapshot类。
如果要绑定到此类,则应实现INotifyPropertyChanged接口。
我完全不了解WPF的内部工作原理,但是当使用像ANTS这样的内存分析器时,您可以看到与您的对象有很多不同的保留图。
例如,您的Snapshot类当前将导致WPF通过反射为您在XAML中绑定的每个属性创建ValueChanged事件处理程序,并且这些属性不能正确清理。实现INotifyPropertyChanged时,不会发生这种情况,并且绑定会自行清除属性。