我开始在PRISM和MVVM上使用WPF。我面临的一个问题是,我找不到一个好地方/最佳实践来取消订阅以前在ViewModel中订阅的EventAggregator事件。以下解决方案 - 在析构函数中调用Unsubscribe - 为时已晚。它只是运行下一个垃圾收集。
public class ViewModel : ViewModelBase
{
public ViewModel()
{
var eventAggregator = ServiceLocator.Current.GetInstance<IEventAggregator>();
eventAggregator.GetEvent<SeriesSelectionChangedEvent>().Subscribe(OnSeriesSelectionChanged);
}
~ViewModel()
{
var eventAggregator = ServiceLocator.Current.GetInstance<IEventAggregator>();
eventAggregator.GetEvent<SeriesSelectionChangedEvent>().Unsubscribe(OnSeriesSelectionChanged);
}
void OnSeriesSelectionChanged(SeriesSelectionChangedEventArgs e)
{
}
}
答案 0 :(得分:4)
取决于你!如果您的应用程序可以在不再需要时通知ViewModel,那么您应该取消订阅。
例如,在我们的项目中,我们有IViewDisposeService。如果view(或其模型)需要确定性终结,则在显示时它会在IViewDisposeService中注册。然后,Core会使用相同的服务来通知已注册的视图,这些视图已从区域中删除。
另一种方法是使用命令。您的模型公开命令,该视图在关闭时必须由视图调用。 ViewModel可以使用命令处理程序取消订阅。
顺便说一句,如果你担心EventAggregator会保存你的ViewModel,那不是问题,因为Prism的EventAggregator使用弱引用。
答案 1 :(得分:3)
有时回来,我也遇到了同样的问题。这就是我们所做的(WPF App)。
<强>代码强>
/// <summary>
/// Falg used to avoid calling dispose multiple times on same user control
/// </summary>
private bool isDisposed;
/// <summary>
/// Dispose
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// If disposing equals true, the method has been called directly
/// or indirectly by a user's code. Managed and unmanaged resources
/// can be disposed. If disposing equals false, the method has been called by the
/// runtime from inside the finalizer and you should not reference
/// other objects, only unmanaged resources can be disposed.
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
if (!this.isDisposed)
{
this.isDisposed = true;
if (disposing)
{
UtilityFunctions.DisposeChildDisposableUserControls(this);
if (this.DataContext != null && this.DataContext is IDisposable)
{
var parent = LogicalTreeHelper.GetParent(this);
if (parent == null || ((parent as FrameworkElement).DataContext != this.DataContext))
{
(this.DataContext as IDisposable).Dispose();
}
BindingOperations.ClearAllBindings(this);
this.DataContext = null;
}
}
}
}
答案 2 :(得分:2)
您可以让View在卸载时通知ViewModel(或者在Window关闭时通知它)。然后在ViewModel中的Unloaded / Closed处理程序中,您可以取消订阅。这就是我在申请中的方式。