【问题标题】:Can I remove duplicating events in EventAggregator?我可以删除 EventAggregator 中的重复事件吗?
【发布时间】:2023-04-04 11:10:01
【问题描述】:

我有一个非常简单的场景,我无法正常工作。我有 2 个视图,即 CarView 和 CarWindowView(子窗口)以及相应的 ViewModel。在我的 CarView 中,我有一个 EditButton,可以打开 CarWindowView(子窗口),我可以在其中编辑 Car 对象字段。

我的问题是我的 CarWindowView ViewModel 中的 DisplayModule 方法被调用太多次...当我第一次按下编辑按钮时,它被调用一次,第二次被调用两次,第三次被调用3次等堡垒...!

CarView ViewModel 构造函数:

Public Sub New(ByVal eventAggregator As IEventAggregator, ByVal con As IUnityContainer, ByVal mgr As ICarManager, ByVal CarService As ICarService)

    _Container = con
    _CarManager = mgr
    _EventAggregator = eventAggregator

    'Create the DelegateCommands
    NewBtnClick = New DelegateCommand(Of Object)(AddressOf HandleNewCarBtnClick)
    EditBtnClick = New DelegateCommand(Of Object)(AddressOf HandleEditCarBtnClick)
End Sub

CarView ViewModel HandleEditCarBtnClick 方法:

Private Sub HandleEditCarBtnClick()

    Dim view = New CarWindowView
    Dim viewModel = _Container.Resolve(Of CarWindowViewModel)()
    viewModel.CurrentDomainContext = DomainContext

    viewModel.CurrentItem = CurrentItem
    viewModel.IsEnabled = False

    view.ApplyModel(viewModel)
    view.Show()

    _EventAggregator.GetEvent(Of CarCollectionEvent)().Publish(EditObject)
End Sub

CarWindowView ViewModel 构造函数:

Public Sub New(ByVal eventAggregator As IEventAggregator, ByVal con As IUnityContainer, ByVal mgr As ICarManager, ByVal CarService As ICarService)

    _Container = con
    _CarManager = mgr
    _EventAggregator = eventAggregator

    _EventAggregator.GetEvent(Of CarCollectionEvent).Subscribe(AddressOf DisplayModule)

End Sub

CarWindowView ViewModel DisplayModule 方法(此方法被调用次数过多):

Public Sub DisplayModule(ByVal param As String)
If param = EditObject Then
  IsInEditMode = True
  ' Logic removed for display reasons here. This logic breaks because it's called too    many times.
  End If
End Sub

所以,我无法理解我如何只能让 EventAggregator 只存储一次单击,而不是我对“编辑”按钮的所有单击。对不起,如果这不是很好的解释!感谢您的帮助!

【问题讨论】:

    标签: silverlight events mvvm prism eventaggregator


    【解决方案1】:

    听起来您的 CarWindowViewModel 存在内存泄漏。换句话说,您有该类的多个实例尚未被垃圾收集。在调试器中,查看 GetHashCode。我敢打赌他们是不同的。

    假设您使用的是 Prism 的 EventAggregator,它应该保持对您的对象的弱引用,所以这不是您的问题。

    您很可能需要确保在该 ViewModel 完成后,它会取消订阅该事件。另外,看看你是否能弄清楚引用链中的什么使它们保持活力。

    【讨论】:

    • 你很可能是正确的,我会调查的。你是什​​么意思; “在调试器中,查看 GetHashCode”——什么是 GetHashCode,在调试过程中如何查看?此外,我在每次 EditBtn 单击时运行这行代码:_Container.Resolve(Of CarWindowViewModel)() 这会导致这种行为吗?
    • 当您在调试器中的类方法中时,在监视窗口中键入 this.GetHashCode()。它将为您的班级提供一个唯一的 ID。使用它,您可以找出您正在查看的实例。类似的机制是将它添加到监视窗口并选择“制作 ID”,它会给它一个更漂亮的 ID 来跟踪它。如果您使用容器来解析 ViewModel,您可能会考虑将其配置为单一生命周期......这样它只会被创建一次。寻找你在课堂上钩住的事件。这是泄漏的常见地方。
    • 你是对的,布赖恩。取消订阅活动解决了我的问题。
    【解决方案2】:

    我认为 EventAggregator 事件是您希望在其他模块中编写的任何旧视图或视图模型都可以收听的事件(或者不收听,随他们的便)。如果我有两个非常依赖于彼此操作的视图并且它们总是存在于同一个逻辑树中,我使用常规的旧 .NET 事件

    我认为只有 “一劳永逸”类型的事件适合 EventAggregator。我知道 Prism 包中的示例似乎提倡在更紧密耦合的主/细节场景中使用它们,但我认为这并不合适(阅读:矫枉过正)。

    虽然这不能直接解决您的问题(我认为您也有内存泄漏),但如果您这样组织它,您可能会完全避免这个问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-31
      • 1970-01-01
      • 2011-11-25
      • 1970-01-01
      • 2019-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多