如何在 Prism 框架中的模块之间正确发送事件消息?
How to correctly send event-messages between modules in Prism framework?
我正在尝试使用 MVVM 设计模式构建基于 WPF Prism 的应用程序。
当我的应用第一次启动时,我想要求用户登录。登录后,我想显示带有用户名和按钮的默认登录页面。
我的想法是,当用户登录时,我会发布一个名为 UserLoggedIn
的事件,然后在主视图模型上,我会监听该事件。当事件被触发时,我会显示 landing/home 视图。
所以我创建了这样的活动
public class UserLoggedIn : PubSubEvent<User>
{
}
然后在 LoginViewModel
我处理登录并像这样发布事件
private void HandleLogin(LoginView loginView)
{
try
{
User user = AuthenticationService.Authenticate(Username, loginView.GetPassport());
IUserPassport passport = PassportManager.Get(user.Username);
if (passport == null)
{
// Create a new session
passport = new UserPassport(new CustomIdentity(user), RegionManager);
}
// Assign the current session
PassportManager.SetCurrent(passport);
// Trigger the event
EventAggregator.GetEvent<UserLoggedIn>().Publish(passport);
// Deactivate the login view
RegionManager.GetMainRegion().Deactivate(loginView);
}
catch (Exception ex)
{
//Do something with the error
}
}
最后,在我的 HomeViewModel
也就是我的着陆视图中,我有以下代码来侦听 UserLoggedIn
事件。
public class HomeViewModel : BindableBase
{
protected IUnityContainer Container { get; set; }
protected ICoreRegionManager RegionManager { get; set; }
private IEventAggregator EventAggregator { get; set; }
public HomeViewModel(IUnityContainer container, ICoreRegionManager regionManager, IEventAggregator eventAggregator)
{
Container = container;
RegionManager = regionManager;
EventAggregator = eventAggregator;
eventAggregator.GetEvent<UserLoggedIn>().Subscribe(ShowTheLangingPage);
}
private void ShowTheLangingPage(User user)
{
var homeView = Container.Resolve<HomeView>();
RegionManager.AddToMainRegion(homeView);
FullName = user.FirstName;
}
// I am using PropertyChange.Fody package, so this propery will automaticly raise the PropertyChange event.
public string FullName { get; set; }
}
问题是 ShowTheLangingPage
方法从未像预期的那样在我的 HomeViewModel
中触发。
我确保视图 HomeView
和 HomeViewModel
连接正确,方法是在模块初始化时直接加载 HomeView
进行测试。
此外,如果在我发布事件之前添加 Container.Resolve<HomeView>();
,我调用的 ShowTheLangingPage
。就像我必须手动解析 HomeView
才能监听事件。
如何正确监听 UserLoggedIn
事件,以便显示相应的视图。
所以我可以学习 better/recommended 方法,从 LoginViewModel
显示着陆视图是否比使用 event/listener 更好...为什么?此外,如果直接从 LoginViewModel
显示着陆视图,那么推荐的导航方法是什么?使用 Region.Add() 方法或 RegionManager.RequestNavigate
?
is it better to show the landing view from the LoginViewModel instead of using event/listener....
是的。
and why?
因为这就是服务(如 IRegionManager
)的用途,为您的视图模型和其他服务做一些事情。另外,您已经注意到,事件只能由活动对象订阅。
Also, if showing the landing view directly from the LoginViewModel then what is the recommended method to navigate; using Region.Add() method or RegionManager.RequestNavigate?
如果有的话,第三个 class 应该监听 UserLoggedIn
,但这与直接使用 IRegionManager
相比没有任何好处。事实上,它更糟糕,因为你必须人为地创建这个class。旁注:如果您在 Container.Resolve<HomeView>();
之后和登录之前等待垃圾收集器,您将不会转到登录页面,因为没有订阅者(再次)。
我正在尝试使用 MVVM 设计模式构建基于 WPF Prism 的应用程序。
当我的应用第一次启动时,我想要求用户登录。登录后,我想显示带有用户名和按钮的默认登录页面。
我的想法是,当用户登录时,我会发布一个名为 UserLoggedIn
的事件,然后在主视图模型上,我会监听该事件。当事件被触发时,我会显示 landing/home 视图。
所以我创建了这样的活动
public class UserLoggedIn : PubSubEvent<User>
{
}
然后在 LoginViewModel
我处理登录并像这样发布事件
private void HandleLogin(LoginView loginView)
{
try
{
User user = AuthenticationService.Authenticate(Username, loginView.GetPassport());
IUserPassport passport = PassportManager.Get(user.Username);
if (passport == null)
{
// Create a new session
passport = new UserPassport(new CustomIdentity(user), RegionManager);
}
// Assign the current session
PassportManager.SetCurrent(passport);
// Trigger the event
EventAggregator.GetEvent<UserLoggedIn>().Publish(passport);
// Deactivate the login view
RegionManager.GetMainRegion().Deactivate(loginView);
}
catch (Exception ex)
{
//Do something with the error
}
}
最后,在我的 HomeViewModel
也就是我的着陆视图中,我有以下代码来侦听 UserLoggedIn
事件。
public class HomeViewModel : BindableBase
{
protected IUnityContainer Container { get; set; }
protected ICoreRegionManager RegionManager { get; set; }
private IEventAggregator EventAggregator { get; set; }
public HomeViewModel(IUnityContainer container, ICoreRegionManager regionManager, IEventAggregator eventAggregator)
{
Container = container;
RegionManager = regionManager;
EventAggregator = eventAggregator;
eventAggregator.GetEvent<UserLoggedIn>().Subscribe(ShowTheLangingPage);
}
private void ShowTheLangingPage(User user)
{
var homeView = Container.Resolve<HomeView>();
RegionManager.AddToMainRegion(homeView);
FullName = user.FirstName;
}
// I am using PropertyChange.Fody package, so this propery will automaticly raise the PropertyChange event.
public string FullName { get; set; }
}
问题是 ShowTheLangingPage
方法从未像预期的那样在我的 HomeViewModel
中触发。
我确保视图 HomeView
和 HomeViewModel
连接正确,方法是在模块初始化时直接加载 HomeView
进行测试。
此外,如果在我发布事件之前添加 Container.Resolve<HomeView>();
,我调用的 ShowTheLangingPage
。就像我必须手动解析 HomeView
才能监听事件。
如何正确监听 UserLoggedIn
事件,以便显示相应的视图。
所以我可以学习 better/recommended 方法,从 LoginViewModel
显示着陆视图是否比使用 event/listener 更好...为什么?此外,如果直接从 LoginViewModel
显示着陆视图,那么推荐的导航方法是什么?使用 Region.Add() 方法或 RegionManager.RequestNavigate
?
is it better to show the landing view from the LoginViewModel instead of using event/listener....
是的。
and why?
因为这就是服务(如 IRegionManager
)的用途,为您的视图模型和其他服务做一些事情。另外,您已经注意到,事件只能由活动对象订阅。
Also, if showing the landing view directly from the LoginViewModel then what is the recommended method to navigate; using Region.Add() method or RegionManager.RequestNavigate?
如果有的话,第三个 class 应该监听 UserLoggedIn
,但这与直接使用 IRegionManager
相比没有任何好处。事实上,它更糟糕,因为你必须人为地创建这个class。旁注:如果您在 Container.Resolve<HomeView>();
之后和登录之前等待垃圾收集器,您将不会转到登录页面,因为没有订阅者(再次)。