2015-10-23 8 views
0

Я пытаюсь понять, как правильно распоряжаться видами и режимами просмотра в среде mvvm. Я столкнулся с одной конкретной проблемой с различными пользовательскими элементами управления (которые по сути являются моими взглядами) и их соответствующими режимами просмотра в среде стыковки (аналогично тому, что вы можете увидеть в визуальной студии).Действительно ли мой ViewModel удаляется

Я читал бесчисленные сообщения, блоги и вопросы здесь и, наконец, нашел то, что, как я думал, работает (действительно, вполне возможно, но я просто не понимаю этот процесс).

В моей модели просмотра я реализую Idiposable и в представлении (которому он задан как его datacontext). Я гарантирую, что вызовы view будут располагаться в своем datacontext при его разгрузке. Таким образом, просмотр закрывается и вызывает dispose на свой datacontext (моя модель просмотра), гарантируя, что я могу очистить все оставшиеся блоки, которые могут зависать и вызывать утечку памяти, например обработчики событий.

Одним из таких ViewModel имеют следующий код в переопределен Dispose подразделов:

' IDisposable 
    Protected Overridable Sub Dispose(disposing As Boolean) 
     If Not disposedValue Then 
      If disposing Then 
       ' TODO: dispose managed state (managed objects). 
      End If 

      ' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below. 
      ' 

      ' 
      If mwvm.CanCallDisposeOnErsSubmissionViewModel Then 
       mwvm = Nothing 
       subEd = Nothing 
       retEd = Nothing 
      End If 

      ' TODO: set large fields to null. 
     End If 
     Try 

      If Not mwvm.CanCallDisposeOnErsSubmissionViewModel Then 
       disposedValue = False 
      End If 
     Catch ex As NullReferenceException 
      disposedValue = True 
     End Try 
     MessageBox.Show("DisposeValue = " & disposedValue.tostring) 
    End Sub 

Это ViewModel ссылка элементы в mainviewmodel заявки (одна из причин, почему я чувствовал, что это было важно, чтобы очистить его после того, как но представление, для которого это контекст данных, перерисовывается, если конечный пользователь либо добавляет, либо закрывает другие окна в док-станции, в которой он сидит (отсюда необходимость условного оператора).

Теперь это может быть не так элегантный, и, возможно, это не лучший способ сделать это, но мой вопрос возникает из наблюдения мычание.

Когда я решила активно закрыть представление, а условные операторы позволяют выполнить очистку и установить значение, равное true, я бы подумал, что это будет означать, что модель обзора была хорошо и по-настоящему закрыта и однако я могу позволить программе продолжать работать, и hey presto up выдает окно сообщения, которое может быть получено только от обработчика выше. Так ли моя модель должным образом отключена, это нормальное поведение (предположительно сборщик мусора, делающий свою вещь, чтобы его можно было игнорировать), или есть какая-то фундаментальная ошибка с моей стороны где-то?

+0

Вы видели этот вопрос? Http: // StackOverflow.com/questions/3258064/what-best-practices-for-cleaning-up-event-обработчик-ссылки – netaholic

+0

Как реализован ваш метод 'Dispose()' (один из интерфейса 'IDisposable', без параметров)? Он должен вызывать 'GC.SuppressFinalize (this);' после вызова 'Dispose (true)'. Это предотвратит вызов GC из Dispose() 'в фактическую сборку мусора (вы не можете контролировать, когда это произойдет, GC делает это). Проверьте MSDN для правильной реализации одноразового шаблона: https://msdn.microsoft.com/en-us/library/system.gc.suppressfinalize(v=vs.110).aspx – Tseng

+0

@Tseng Большой вызов, спасибо, это точно что я пропустил. Отметьте это как ответ, а не только так, чтобы я мог принять его, но также и как простой способ для любого, кто задается вопросом о том, чтобы определить его. –

ответ

1

При использовании одноразового использования шаблона, вы должны вызвать GC.SuppressFinalize(this) внутри Dispose() для подавления GC от вызова метода Dispose(), когда он завершит объект (так как вы не имеете никакого контроля о том, когда ГХ делает это)

Из MSDN на Disposable Pattern:

public class DisposableResourceHolder : IDisposable { 

    private SafeHandle resource; // handle to a resource 

    public DisposableResourceHolder(){ 
     this.resource = ... // allocates the resource 
    } 

    public void Dispose(){ 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    protected virtual void Dispose(bool disposing){ 
     if (disposing){ 
      if (resource!= null) resource.Dispose(); 
     } 
    } 
} 

добавить к тому, Цзэн уже сказал, но по отношению конкретно к VB.

Если вы реализуете IDisposable на классе в VB следующий код котла пластина будет добавлена ​​к классу:

#Region "IDisposable Support" 
Private disposedValue As Boolean ' To detect redundant calls 

' IDisposable 
Protected Overridable Sub Dispose(disposing As Boolean) 
    If Not disposedValue Then 
     If disposing Then 
      ' TODO: dispose managed state (managed objects). 
     End If 

     ' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below. 
     ' TODO: set large fields to null. 
    End If 
    disposedValue = True 
End Sub 

' TODO: override Finalize() only if Dispose(disposing As Boolean) above has code to free unmanaged resources. 
'Protected Overrides Sub Finalize() 
' ' Do not change this code. Put cleanup code in Dispose(disposing As Boolean) above. 
' Dispose(False) 
' MyBase.Finalize() 
'End Sub 

' This code added by Visual Basic to correctly implement the disposable pattern. 
Public Sub Dispose() Implements IDisposable.Dispose 
    ' Do not change this code. Put cleanup code in Dispose(disposing As Boolean) above. 
    Dispose(True) 
    ' TODO: uncomment the following line if Finalize() is overridden above. 
    ' GC.SuppressFinalize(Me) 
End Sub 

Stackoverflow фактически выделяет код в более доступной форме, чем Visual Studio редактор делает. Я добавил, что бит, который, как я знал, нужно было отнести к Overridable Sub Dispose. Я принял к сведению комментарий в этом разделе, чтобы расколоть раздел Ovveride Finalize. То, что я пропустил, состояло в том, чтобы продолжить и раскомментировать строку GC.SuppressFinalize (Me) в фактическом методе Dispose. Глупой ошибкой с моей стороны единственным оправданием, которое я могу предложить, является то, что зеленые комментарии слишком хорошо сочетают вещи.

Надеюсь, это поможет другим.

+0

OP предложила существенное изменение для добавления дополнительной информации. – Will