My Application’s designed by MVVM.
Main window is MainWindow.xaml as below. Main Window has two usercontrols.
By the way, usercontrol is created dynamically in run-time, when property of viewmodel is changed.
But it seems my application has memory leak.
MainWindow.xaml
<Window x:Class="InstanceTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:InstanceTest"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:MainWindowViewModel x:Key="MainWindowViewModel" />
<DataTemplate x:Key="UD1">
<ContentControl>
<local:UserControl1></local:UserControl1>
</ContentControl>
</DataTemplate>
<DataTemplate x:Key="UD2">
<ContentControl>
<local:UserControl2></local:UserControl2>
</ContentControl>
</DataTemplate>
<DataTemplate x:Key="contentsTemplate">
<ContentControl>
<ContentControl.Style>
<Style TargetType="ContentControl">
<Style.Triggers>
<DataTrigger Binding="{Binding ViewType}" Value="1">
<Setter Property="ContentTemplate" Value="{DynamicResource UD1}" />
</DataTrigger>
<DataTrigger Binding="{Binding ViewType}" Value="2">
<Setter Property="ContentTemplate" Value="{DynamicResource UD2}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</DataTemplate>
</Window.Resources>
<Grid DataContext="{StaticResource MainWindowViewModel}">
<StackPanel>
<Button Height="30" Command="{Binding ChangeViewCommand}">ChangeView</Button>
<ContentControl Content="{Binding}" ContentTemplate="{StaticResource contentsTemplate}" />
</StackPanel>
</Grid>
MainWindow.xaml is related to MainWindowViewModel.cs.
According to ViewType property, each usercontrol is created dynamically in run time.
public class MainWindowViewModel : ViewModelBase
{
private string viewType;
public string ViewType
{
get { return viewType; }
set
{
viewType = value;
base.RaisePropertyChanged(() => this.ViewType);
}
}
public MainWindowViewModel()
{
ChangeViewCommand = new RelayCommand(ChangeView);
}
public ICommand ChangeViewCommand { get; private set; }
private void ChangeView(object o)
{
int aa = 1000;
while (aa > 0)
{
System.Threading.Thread.Sleep(1000);
System.Windows.Forms.Application.DoEvents();
if (ViewType == "1")
ViewType = "2";
else
ViewType = "1";
aa--;
//GC.Collect();
}
}
}
UserControl1.xaml
<UserControl.Resources>
<local:uc1ViewModel x:Key="uc1ViewModel" />
</UserControl.Resources>
<Grid DataContext="{StaticResource uc1ViewModel}">
<StackPanel>
<TextBlock FontSize="30" Text="{Binding TextExample}"></TextBlock>
<Image Source="/InstanceTest;component/Images/sample.jpg" />
</StackPanel>
</Grid>
UserControl1.xaml has uc1ViewModel.cs. UserControl2.xaml has uc2ViewModel.cs as below.
public class uc1ViewModel : ViewModelBase
{
private string textExample;
public string TextExample
{
get { return textExample; }
set
{
textExample = value;
base.RaisePropertyChanged(() => this.TextExample);
}
}
public uc1ViewModel()
{
TextExample = "UD1...";
}
~uc1ViewModel()
{
Debug.WriteLine("Call Destructor");
}
}
ChangeView Function of MainViewModel.cs changes ViewType property every second.
When changing property of ViewType, ui1ViewModel is created as new instance. If ui1ViewModel’s instance is created for the next time, I expect old instance of ui1ViewModel is removed by garbage collector.
But, it looks like application has memory leak when testing for bunch of times.
I checked destructor of ui1ViewModel
and type Debug.WriteLine(“Call Destructor”) at destructor. but it dosen’t call every times.
When I call GC.Collect() by force, destructor of ui1ViewModel is called and reduce memory size of application.
So, my question is
Can I call GC.collect() by force in this case? or do you have other way to solve this problem?
I don’t think it is a memory leak either:
Raymond Chen has a nice explanation on what people wrongly understand by Garbage Collection:
http://blogs.msdn.com/b/oldnewthing/archive/2010/08/09/10047586.aspx
I’ll always remember this: