1

バインディングに関連していると思われる奇妙な動作をしています。基本的に、ViewModelでのコントロールのバインドにより、PropertyChangedイベントからコントロールへの強力な参照が作成されると思われます。したがって、ViewModelは常にコントロールへの参照を保持します。したがって、コントロールは使い終わったとしても、常にメモリに保持されます。これは、ViewModelを破棄するまで残りますが、私の場合は、すべてに対して1つのViewModelがあります。バインディングによって作成されたイベントのフックを解除する方法はありますか?

これが私の問題のより詳細な説明であり、私を上記の信念に導いたものです:

私はViewModelを持っています:

public ViewModel()
{
    InitializeCommands();
}

public ICommand OpenPropertiesCommand { get; set; }

private void InitializeCommands()
{
    OpenPropertiesCommand = new DelegateCommand((o) =>
    {
        OpenProperties(o as ContentControl);
    });
}

private void OpenProperties(ContentControl propertiesWindowOwner)
{
    JobProperties jp = new JobProperties(this);
    jp.WindowStartupLocation = Telerik.Windows.Controls.WindowStartupLocation.CenterOwner;
    jp.Owner = propertiesWindowOwner;
    jp.ShowDialog();
}

private Job selectedJob;
public Job SelectedJob
{
    get
    {
        return selectedJob;
    }
    set
    {
        selectedJob = value;
        RaisePropertyChanged("SelectedJob");
    }
}

このViewModelは私のメインコントロールによって使用されます。このコントロールには、各行が「ジョブ」であるGridViewがあります。ジョブのプロパティを編集できます。これにより、各ジョブのプロパティを編集できるRadWindowコントロールが開きます。

私のPropertyEditコントロールは、DataContextと同じViewModelを使用するRadWindowです。そのすべてのコンポーネントは、何かがJobのプロパティであるSelectedJob.somethingにバインドされます。

ジョブ#1のプロパティを開いた場合。PropertyEditコントロールが作成され、バインディングが確立されます。私のプロパティSelectedJob.somethingは、必要に応じてバインディングごとに1回アクセスされます。PropertyEditコントロールを閉じて、ジョブ#1のプロパティを再度開いた場合。もう1つのPropertyEditコントロールが作成され、バインディングが確立されます。これを閉じて別のジョブを選択すると、selectedJobでPropertyChangedイベントが呼び出され、バインディングごとにバインディングが2回呼び出されます。実際には、最初のPropertyEditコントロールバインディングがアクティブ化され、2番目のPropertyEditバインディングもアクティブ化されます。ここで、ジョブ#1のプロパティを100回開いた場合、ジョブ#2を選択すると、バインディングはそれぞれに対して100回照会されます。したがって、バインディングがPropertyEditコントロールをメモリに保持しているメモリリークが疑われます。それらすべてへの参照を保持しているためです。ViewModelを破棄するまで、これらの参照は保持されますが、私の場合、これはメインアプリのViewModelであり、破棄されることはありません。どうすればこれを防ぐことができますか?バインディングのイベントを手動で登録解除する方法はありますか?

ありがとうございました。

4

1 に答える 1

0

私はこの問題を解決しました。問題はバインディングにはありませんでしたが、ウィンドウの所有者プロパティが何らかの理由でウィンドウのガベージ コレクションを停止しているようです。

この行をコメントアウトすることにより:

jp.Owner = propertiesWindowOwner;

問題を解決しました。これがなぜなのかわかりません。ウィンドウの所有者を設定すると、ウィンドウが propertiesWindowOwner の子として設定されるという副作用があると思われます。したがって、propertiesWindowOwner を破棄するまで、ウィンドウを閉じた後でもウィンドウへの参照が保持されます。

なぜこれが起こるのか、そしてこれを行うときにメモリをリークしないようにする必要があるのか​​ について少し混乱しています。これについて知っている人はコメントしてください。

于 2012-11-14T19:31:02.400 に答える