使用 IEventAggregator 的 Caliburn 微堆栈溢出异常
Caliburn Micro Stack Overflow Exception using IEventAggregator
我正在学习并尝试 MVVM
使用 Caliburn.Micro
。我有一个主 ShellViewModel
和一个子用户控件 Module1ViewModel
。我正在尝试使用 IEventAggregator
.
实现它们之间的通信
现在,我可以从子控件 ShellViewModel 更改 ShellViewModel
(父)的 属性,并且可以从父控件更改 属性 的子控件,它可以工作。
问题: 我面临的问题是,当我在两个 ViewModel 中启用 events.Subscribe(this);
时,出现异常。
我想要实现的是双向 种沟通方式。这意味着我想同时从子项中更改一些 属性 的父项,我应该能够从父项中更改一些 属性 的子项。以下是我的代码,请检查这里有什么问题。
子用户控制模块1ViewModel
namespace IntelliCoreMVVM.ViewModels
{
public class Module1ViewModel:Screen , IHandle<string>
{
private IEventAggregator _events;
public Module1ViewModel(IEventAggregator events)
{
_events = events;
events.Subscribe(this);
}
private string _firstName;
public string FirstName
{
get { return _firstName; }
set
{
_firstName = value;
NotifyOfPropertyChange(()=>FirstName);
_events.PublishOnUIThread(FirstName);
}
}
public void Handle(string message)
{
FirstName = message;
}
}
}
如您所见,我正在发布和处理 属性。
ShellViewModel
public class ShellViewModel : Conductor<object> , IHandle<string>
{
private Module1ViewModel _module1ViewModel;
private IEventAggregator _events;
public ShellViewModel(Module1ViewModel module1ViewModel,IEventAggregator events)
{
_events = events;
events.Subscribe(this);
_module1ViewModel = module1ViewModel;
}
private string _test;
private string _firstName;
public string FirstName
{
get { return _firstName; }
set
{
_firstName = value;
NotifyOfPropertyChange(()=>FirstName);
_events.PublishOnUIThread(new CustomerModel{FirstName = FirstName});
}
}
public string Test
{
get { return _test; }
set
{
_test = value;
NotifyOfPropertyChange(()=>Test);
}
}
public void Handle(string message)
{
Test = message;
}
}
快速观看
堆栈调用
问题是您的 VM 正在递归地相互更新和自我更新,例如订阅 IEventAggregator
并处理字符串消息,而不是更新 属性 并再次发布相同的消息,某种无限循环。您可以引入一个类型化的事件来处理从父到子,反之亦然,而不仅仅是字符串
public class ChildEvent
{
public string Name { get; set; }
}
public class ParentEvent
{
public string Name { get; set; }
}
public class ShellViewModel : Conductor<object>, IHandle<ChildEvent>
{
private readonly IEventAggregator _events;
public ShellViewModel(IEventAggregator events)
{
_events = events;
events.Subscribe(this);
}
private string _test;
public string Test
{
get => _test;
set
{
_test = value;
NotifyOfPropertyChange(() => Test);
}
}
public void Handle(ChildEvent message)
{
Test = message.Name;
}
}
public class Module1ViewModel : Screen, IHandle<ParentEvent>
{
private readonly IEventAggregator _events;
public Module1ViewModel(IEventAggregator events)
{
_events = events;
events.Subscribe(this);
}
private string _firstName;
public string FirstName
{
get => _firstName;
set
{
_firstName = value;
NotifyOfPropertyChange(() => FirstName);
}
}
public void Handle(ParentEvent message)
{
FirstName = message.Name;
}
}
顺便说一句,在使用 IEventAggregator
的情况下,您不需要 ShellViewModel
中的 Module1ViewModel
引用。也不要在 setter 中立即触发事件,因为它可以在视图模型之间触发无限事件循环
FirstName
引发调用 Handle
的事件,它再次设置 FirstName
然后它在无限循环中像这样继续下去,直到你 运行 出栈 space 并得到 WhosebugException
.
问题是 Module1ViewModel
处理 所有 string
事件,包括它自己引发的事件。
您可能想要做的是定义不同类型的事件,以便您可以区分它们并选择要处理的事件。在下面的示例中,Module1ViewModel
处理类型 ParentToChildEvent
的事件,但它引发类型 ChildToParentEvent
的事件。 ShellViewModel
应该相反。
public class Module1ViewModel : Screen, IHandle<ParentToChildEvent>
{
private IEventAggregator _events;
public Module1ViewModel(IEventAggregator events)
{
_events = events;
events.Subscribe(this);
}
private string _firstName;
public string FirstName
{
get { return _firstName; }
set
{
_firstName = value;
_events.PublishOnUIThread(new ChildToParentEvent(FirstName));
}
}
public void Handle(string message)
{
FirstName = message;
}
}
我正在学习并尝试 MVVM
使用 Caliburn.Micro
。我有一个主 ShellViewModel
和一个子用户控件 Module1ViewModel
。我正在尝试使用 IEventAggregator
.
实现它们之间的通信
现在,我可以从子控件 ShellViewModel 更改 ShellViewModel
(父)的 属性,并且可以从父控件更改 属性 的子控件,它可以工作。
问题: 我面临的问题是,当我在两个 ViewModel 中启用 events.Subscribe(this);
时,出现异常。
我想要实现的是双向 种沟通方式。这意味着我想同时从子项中更改一些 属性 的父项,我应该能够从父项中更改一些 属性 的子项。以下是我的代码,请检查这里有什么问题。
子用户控制模块1ViewModel
namespace IntelliCoreMVVM.ViewModels
{
public class Module1ViewModel:Screen , IHandle<string>
{
private IEventAggregator _events;
public Module1ViewModel(IEventAggregator events)
{
_events = events;
events.Subscribe(this);
}
private string _firstName;
public string FirstName
{
get { return _firstName; }
set
{
_firstName = value;
NotifyOfPropertyChange(()=>FirstName);
_events.PublishOnUIThread(FirstName);
}
}
public void Handle(string message)
{
FirstName = message;
}
}
}
如您所见,我正在发布和处理 属性。
ShellViewModel
public class ShellViewModel : Conductor<object> , IHandle<string>
{
private Module1ViewModel _module1ViewModel;
private IEventAggregator _events;
public ShellViewModel(Module1ViewModel module1ViewModel,IEventAggregator events)
{
_events = events;
events.Subscribe(this);
_module1ViewModel = module1ViewModel;
}
private string _test;
private string _firstName;
public string FirstName
{
get { return _firstName; }
set
{
_firstName = value;
NotifyOfPropertyChange(()=>FirstName);
_events.PublishOnUIThread(new CustomerModel{FirstName = FirstName});
}
}
public string Test
{
get { return _test; }
set
{
_test = value;
NotifyOfPropertyChange(()=>Test);
}
}
public void Handle(string message)
{
Test = message;
}
}
快速观看
堆栈调用
问题是您的 VM 正在递归地相互更新和自我更新,例如订阅 IEventAggregator
并处理字符串消息,而不是更新 属性 并再次发布相同的消息,某种无限循环。您可以引入一个类型化的事件来处理从父到子,反之亦然,而不仅仅是字符串
public class ChildEvent
{
public string Name { get; set; }
}
public class ParentEvent
{
public string Name { get; set; }
}
public class ShellViewModel : Conductor<object>, IHandle<ChildEvent>
{
private readonly IEventAggregator _events;
public ShellViewModel(IEventAggregator events)
{
_events = events;
events.Subscribe(this);
}
private string _test;
public string Test
{
get => _test;
set
{
_test = value;
NotifyOfPropertyChange(() => Test);
}
}
public void Handle(ChildEvent message)
{
Test = message.Name;
}
}
public class Module1ViewModel : Screen, IHandle<ParentEvent>
{
private readonly IEventAggregator _events;
public Module1ViewModel(IEventAggregator events)
{
_events = events;
events.Subscribe(this);
}
private string _firstName;
public string FirstName
{
get => _firstName;
set
{
_firstName = value;
NotifyOfPropertyChange(() => FirstName);
}
}
public void Handle(ParentEvent message)
{
FirstName = message.Name;
}
}
顺便说一句,在使用 IEventAggregator
的情况下,您不需要 ShellViewModel
中的 Module1ViewModel
引用。也不要在 setter 中立即触发事件,因为它可以在视图模型之间触发无限事件循环
FirstName
引发调用 Handle
的事件,它再次设置 FirstName
然后它在无限循环中像这样继续下去,直到你 运行 出栈 space 并得到 WhosebugException
.
问题是 Module1ViewModel
处理 所有 string
事件,包括它自己引发的事件。
您可能想要做的是定义不同类型的事件,以便您可以区分它们并选择要处理的事件。在下面的示例中,Module1ViewModel
处理类型 ParentToChildEvent
的事件,但它引发类型 ChildToParentEvent
的事件。 ShellViewModel
应该相反。
public class Module1ViewModel : Screen, IHandle<ParentToChildEvent>
{
private IEventAggregator _events;
public Module1ViewModel(IEventAggregator events)
{
_events = events;
events.Subscribe(this);
}
private string _firstName;
public string FirstName
{
get { return _firstName; }
set
{
_firstName = value;
_events.PublishOnUIThread(new ChildToParentEvent(FirstName));
}
}
public void Handle(string message)
{
FirstName = message;
}
}