取消订阅ViewModels中的EventAggregator事件

时间:2011-04-28 15:56:11

标签: wpf mvvm prism

我开始在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)
    {
    }
}

3 个答案:

答案 0 :(得分:4)

取决于你!如果您的应用程序可以在不再需要时通知ViewModel,那么您应该取消订阅。

例如,在我们的项目中,我们有IViewDisposeService。如果view(或其模型)需要确定性终结,则在显示时它会在IViewDisposeService中注册。然后,Core会使用相同的服务来通知已注册的视图,这些视图已从区域中删除。

另一种方法是使用命令。您的模型公开命令,该视图在关闭时必须由视图调用。 ViewModel可以使用命令处理程序取消订阅。

顺便说一句,如果你担心EventAggregator会保存你的ViewModel,那不是问题,因为Prism的EventAggregator使用弱引用。

答案 1 :(得分:3)

有时回来,我也遇到了同样的问题。这就是我们所做的(WPF App)。

  1. 创建一个新的基类 - DisposableUserControl :UserControl,IDisposable。这将包含处理用户控件的逻辑。代码最后添加。
  2. 使用DisposableUserControl替换应用程序中的所有用户控件。喜欢&lt; app:DisposableUserControl ....&gt; &LT; / app.DisposableUserControl&gt;
  3. 在ViewModelBase中添加OnDispose方法(虚拟),该方法在VM的Dispose()方法中调用。应用程序的ViewModel应覆盖此OnDispose方法,在该方法中您将取消订阅事件。喜欢的东西 -
    OnDispose(){base.Dispose(); UnsubscribeEvent(abcEventSubscribername); }
  4. <强>代码

        /// <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处理程序中,您可以取消订阅。这就是我在申请中的方式。