2012-10-05 1 views
1

나는 Binding과 관련 있다고 생각하는 이상한 행동을하고 있습니다. 기본적으로 ViewModel에 내 컨트롤을 바인딩하면 PropertyChanged 이벤트에서 컨트롤에 대한 강력한 참조가 만들어집니다. 따라서 ViewModel은 항상 컨트롤에 대한 참조를 유지합니다. 따라서, 비록 내가 통제로 끝났지 만, 그들은 항상 기억에 보관됩니다. 내 ViewModel을 파괴 할 때까지이 상태가 유지되지만, 제 경우에는 모든 것에 대해 하나의 ViewModel이 있습니다. 바인딩에 의해 생성 된 이벤트를 unhook 할 수있는 방법이 있습니까?바인딩은 내 컨트롤이 완료된 후에도 내 컨트롤을 유지합니다. 어떻게 그들을 풀 수 있습니까?

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"); 
    } 
} 

이 뷰 모델은 내 메인 컨트롤에 의해 사용되는 : 나는 뷰 모델이

: 여기

내 문제에 대한 자세한 설명, 그리고 위의 신념에 저를 이어질 것입니다. 이 컨트롤에는 각 행이 "작업"인 GridView가 있습니다. 작업의 속성을 편집하면 각 작업의 속성을 편집 할 수있는 RadWindow 컨트롤이 열립니다.

내 PropertyEdit 컨트롤은 DataContext와 동일한 ViewModel을 사용하는 RadWindow입니다. 그것의 모든 구성 요소는 뭔가가 Job의 속성 인 SelectedJob.something에 바인딩됩니다.

작업 # 1 속성을 열면. PropertyEdit 컨트롤이 만들어지고 바인딩이 설정됩니다. 내 속성 SelectedJob.something은 각 바인딩에 대해 한 번 액세스해야합니다. PropertyEdit 컨트롤을 닫고 작업 # 1 속성을 다시 열면. PropertyEdit 컨트롤이 하나 더 만들어지고 바인딩이 설정됩니다. 이제이 작업을 닫고 다른 작업을 선택하면 selectedJob에서 PropertyChanged 이벤트가 호출되고 각 바인딩에 대해 내 바인딩이 두 번 호출됩니다. 실제로 첫 번째 PropertyEdit 컨트롤 바인딩이 활성화되고 두 번째 PropertyEdit 바인딩도 활성화됩니다. 이제 Job # 1 속성을 100 번 열었을 때 Job # 2를 선택하면 바인딩 하나 하나마다 100 번 쿼리됩니다. 따라서 메모리 누수가 의심 스럽습니다. 바인딩이 내 PropertyEdit 컨트롤을 메모리에 유지하는 이유는 바인딩이 모두에 대한 참조를 보유하기 때문입니다. 내 ViewModel을 파괴 할 때까지 이러한 참조가 유지되지만 내 경우에는 Main App의 ViewModel이므로 절대 삭제되지 않습니다. 어떻게 이런 일이 일어나지 않도록 할 수 있습니까? 바인딩의 이벤트를 수동으로 등록 취소 할 수있는 방법이 있습니까?

감사합니다.

+0

ViewModel을 파괴 할 때까지 해당 컨트롤이 메모리에있는 것을 어떻게 보았습니까? – sll

+0

@sll : 내 ViewModel에서 컨트롤에 바인딩 된 내 속성 중 하나의 getter에 중단 점을 설정합니다. PropertyEdit 컨트롤 하나를 열고 SelectedJob을 변경하면 한 번에 깨집니다. 10 개를 열고 모두 닫은 다음 다른 작업을 선택하면 SelectedJob이 속성 변경 이벤트를 발생 시키므로 중단 점은 10 번 중단됩니다. 일단 내가 내 ViewModel을 삭제하면 내 컨트롤이 가비지 수집 될지 실제로 테스트하지 않았습니다. 다른 사람이 참조를 유지할 수 있는지 알지 못하기 때문에 가정합니다. –

+0

모든 컨트롤에서 또는 사용자 정의 컨트롤에서만 발생합니까? – zapico

답변

0

이 문제가 해결되었습니다. 문제는 바인딩과 관련이 없었지만 Window의 소유자 속성이 어떻게 든 창이 가비지 수집되지 않도록합니다.

이 줄을 주석으로 :

jp.Owner = propertiesWindowOwner; 

나는이 문제를 해결했다. 이것이 왜 있는지 나는 확신하지 못한다. 윈도우의 소유자를 설정하면 윈도우를 propertiesWindowOwner의 자식으로 설정하는 부작용이 있다고 의심됩니다. 따라서 propertiesWindowOwner를 제거하기 전까지는 창을 닫은 후에도 내 창에 대한 참조가 유지됩니다.

왜 이런 일이 발생하는지 혼란스러워하며 이것을 할 때 메모리가 누출되지 않도록해야합니다. 누구든지 알고 있다면이 점에 대해 의견을 말하십시오.

+0

더 많은 조사가 끝나면 내 Window 컨트롤은 Telerik에서 만든 컨트롤이므로 RadWindow이며 소유자 속성 내부에서 메모리 누수가 발생하는 알려진 버그가 있습니다. –

관련 문제