2012-09-26 3 views
2

최근에 datacontext changed 이벤트를 사용하여 실버 라이트 문제를 발견했습니다.왜 DataContextChanged를 구독 취소하면 컬렉션이 변경되어 InvalidOperation 예외가 발생합니까?

당신이 변경된 일정에 가입 한 후 즉시이 예외가 발생합니다 취소하는 경우,

DataContextChanged += MainPage_DataContextChanged; 
void MainPage_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) 
{ 
    var vm = e.NewValue as VM; 
    if(vm != null) 
    { 
    DataContextChange-= MainPage_DataContextChanged;//throws invalidoperationexception for collection modified 
    } 
} 

는 요구 사항이 조만간 구독을 취소하는 것입니다 난 그냥이 상황에서, 나중에 이벤트를 구독 취소이 문제를 해결하려면 그래서 이것은 작동합니다. 내가 컬렉션을 추측하고있어

DataContextChanged += MainPage_DataContextChanged; 
void MainPage_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) 
{ 
    var vm = e.NewValue as VM; 
    if(vm != null) 
    { 
     //forces item onto the dispatcher queue so anything needing to happen with 'collections' happens first 
     Dispatcher.BeginInvoke(()=> 
     { 
    DataContextChange-= MainPage_DataContextChanged;//throws invalidoperationexception for collection modified 
     }); 
    } 
} 

는 시각적 트리에있는 모든 다른 컨트롤의 자식 요소이며, 나는 내 질문이 그래서 그들의 업데이트 아마 디스 큐에 일어나고 같은데요 :

이벤트가 해지 된 후 구독 취소되는 이유가 이후에 수정되거나 업데이트 될 컬렉션에 영향을주는 이유는 무엇입니까?

EDIT : 이 문제를 생각한 후에이 작업은 완료되기 전에 수정되는 이벤트 처리기 호출 목록과 관련이 있습니까?

+0

예외가있는 메시지가 표시됩니까? – Patrick

답변

3

수정중인 호출 목록에 대한 의문 사항이 올바른지 확인하십시오. 여기

는 dotPeek의 디 컴파일에 따르면, DataContextChanged 이벤트를 발생 코드입니다 :
private void RaisePublicDataContextChanged() 
{ 
    if (this._dataContextChangedInfo == null) 
    return; 
    object oldValue = this._dataContextChangedInfo.OldValue; 
    object dataContext = this.DataContext; 
    if (oldValue == dataContext) 
    return; 
    this._dataContextChangedInfo.OldValue = dataContext; 
    List<DependencyPropertyChangedEventHandler>.Enumerator enumerator = this._dataContextChangedInfo.ChangedHandlers.GetEnumerator(); 
    try 
    { 
    // ISSUE: explicit reference operation 
    while (((List<DependencyPropertyChangedEventHandler>.Enumerator) @enumerator).MoveNext()) 
    { 
     // ISSUE: explicit reference operation 
     ((List<DependencyPropertyChangedEventHandler>.Enumerator) @enumerator).get_Current()((object) this, new DependencyPropertyChangedEventArgs(FrameworkElement.DataContextProperty, oldValue, dataContext)); 
    } 
    } 
    finally 
    { 
    enumerator.Dispose(); 
    } 
} 

당신이 볼 수 있듯이

는, 코드가 핸들러의 컬렉션을 반복하는 열거자를 사용하고 있습니다. 따라서 처리기를 호출하는 동안 이벤트 구독을 취소하면 열거자를 무효화하여보고있는 예외를 발생시킵니다.

+0

끝내 주셔서 감사합니다! – tam

관련 문제