When I bind an ItemsSource of a ListBox to a List the binding engine holds on to the list elements after the control is gone. This causes all the list elements to stay in memory. The problem goes away when using an ObservalbleCollection. Why does this happen?
The xaml inside the window tag
<Grid>
<StackPanel>
<ContentControl Name="ContentControl">
<ListBox ItemsSource="{Binding List, Mode=TwoWay}" DisplayMemberPath="Name"/>
</ContentControl>
<Button Click="Button_Click">GC</Button>
</StackPanel>
</Grid>
Code behind:
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.DataContext = null;
ContentControl.Content = null;
GC.Collect();
GC.WaitForPendingFinalizers();
}
ViewModel
class ViewModel : INotifyPropertyChanged
{
//Implementation of INotifyPropertyChanged ...
//Introducing ObservableCollection as type resolves the problem
private IEnumerable<Person> _list =
new List<Person> { new Person { Name = "one" }, new Person { Name = "two" } };
public IEnumerable<Person> List
{
get { return _list; }
set
{
_list = value;
RaisePropertyChanged("List");
}
}
class Person
{
public string Name { get; set; }
}
Edit: To check the leaking of the person istances, I used ANTS and .Net memory profiler. Both show that after pushing the GC-button only the binding engine is holding reference to the person objects.
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…