LINQtoSQLを使用してSQLServerデータベースに接続するWPFアプリを構築しています。
アプリのメインウィンドウにはListView
、一連の詳細ビューが含まれています。のItemSource
はListView
、ルートビューモデルのプロパティとして公開されている詳細ビューモデルオブジェクトのコレクションにバインドされています。各詳細ビューモデルオブジェクトは、いくつかICommand
のプロパティと、詳細モデルオブジェクトを公開するプロパティを構成します。これにより、UIに表示されるさまざまなデータフィールドが公開されます。
ANTSメモリプロファイラーを使用した分析では、リークされているオブジェクトは、詳細モデルオブジェクトに含まれているオブジェクトと、それらがバインドされている一部のUIクラスであることが示されています。以前の更新からのこれらのオブジェクトのインスタンスは、ガベージコレクションされていません。
ANTSには、ユーザーが参照チェーンをトレースして、不要なメモリが保持されている理由を特定できるツールがあります。私がそれを使うとき、私は現れるすべての鎖がICommand
それらの中にあるのを見つけます。したがって、問題のあるものを削除したICommand
ところ、メモリリークが解消されていることがわかりました。
残念ながら、ICommand
いくつかの重要な機能を実装する必要があります。私を本当に混乱させているのは、そもそも詳細モデルオブジェクトへの参照があることです。これらは、詳細ビューモデルオブジェクト内の2つの完全に別個のインスタンス変数です。
詳細ビューモデルオブジェクトのコンストラクターは次のとおりです(RootViewModelへの参照は、ICommandsに接続されている一部のメソッドのコールバックに使用されます。これにより、参照の循環チェーンが発生している可能性があります。問題がありますが、それを削除しても効果はないようです。)
public CarDataViewModel(CarData carDataItem, RootViewModel parentViewModel)
{
_parentViewModel = parentViewModel;
CarDataModel = carDataItem;
CompetingCheckboxStatus = CarDataModel.CurrentCar.Competing;
AcknowledgeAlarm = new ParameterlessCommand(AcknowledgeAlarmClicked);
Acknowledge = new ParameterlessCommand(AcknowledgeClicked);
ShowReport = new ParameterlessCommand(ShowReportClicked);
Cancel = new ParameterlessCommand(CancelClicked);
}
バインディングが設定されているxamlは次のとおりです。AcknowledgeAlarmはICommand、CarDataModelは詳細モデルオブジェクトです。
<ListView x:Name="itemGridView"Grid.Row="1"ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemsSource="{Binding CarDataViewModels}" IsSynchronizedWithCurrentItem="True" Margin="0,0,0,0">
<ListView.ItemTemplate>
<DataTemplate>
</DataTemplate.Resources>
<Button Command="{Binding AcknowledgeAlarm}">
<Border DataContext="{Binding CarDataModel}" BorderBrush="{StaticResource GrayFadeBrush}" Background="White" BorderThickness="5">
<Grid> . . .