Wpf Prism2/MVVM从ViewModel关闭视图
如何从视图模型中关闭视图Wpf Prism2/MVVM从ViewModel关闭视图,wpf,mvvm,prism,Wpf,Mvvm,Prism,如何从视图模型中关闭视图 我有一个WPF窗口,它定义了多个区域,并被用作外壳来承载我的应用程序的视图。我希望有一个视图能够从区域中移除自己,或者从选项卡式容器中关闭它。如何从ViewModel实现此行为。由于您的ViewModel没有(也不应该)对视图的引用,因此无法直接关闭它。但是,您可以在视图模型中添加一个事件,以指示它要关闭 Josh Smith写了一篇文章,展示了如何做到这一点(大约在文章的一半)。这实际上取决于你的应用程序架构,但下面是我如何使用Prism做到这一点的 首先,我想说,让
我有一个WPF窗口,它定义了多个区域,并被用作外壳来承载我的应用程序的视图。我希望有一个视图能够从区域中移除自己,或者从选项卡式容器中关闭它。如何从ViewModel实现此行为。由于您的
ViewModel
没有(也不应该)对视图的引用,因此无法直接关闭它。但是,您可以在视图模型
中添加一个事件
,以指示它要关闭
Josh Smith写了一篇文章,展示了如何做到这一点(大约在文章的一半)。这实际上取决于你的应用程序架构,但下面是我如何使用Prism做到这一点的
首先,我想说,让VM引用视图是可以的,只要它不是视图的具体实现,即,按接口引用
我使用依赖注入将视图和视图模型结合起来,这与StockTraderRI中的做法非常相似。所以我有一个IView和一个IView模型。IViewModel有一个名为“视图”的属性,类型为IView
从代码层(对我来说,通常是控制器…请参阅StockTraderRI)中,添加从区域中删除视图的机制
例如:
myRegion.Remove(myIViewModel.View);
如果区域由控制器处理,您可能希望在VM上放置一个简单事件,以便在VM希望“关闭”时发出通知。如果希望使用弱事件模型,还可以使用IEventAggregator进行实验。如果在VM中处理该区域,只需在那里添加该代码。我的登录模块如下所示:
public class LoginModule : IModule
{
private readonly IUnityContainer container;
public LoginModule(IUnityContainer container)
{
this.container = container;
}
#region IModule Members
public void Initialize()
{
this.container.RegisterType<ILoginController, LoginController>(new ContainerControlledLifetimeManager());
this.container.RegisterType<ILoginView, LoginView>();
this.container.RegisterType<ILoginViewModel, LoginViewModel>();
ILoginController controller = this.container.Resolve<ILoginController>();
controller.Run();
}
#endregion
}
这是我的ViewModel:
public class LoginViewModel : ViewModelBase, ILoginViewModel
{
IEventAggregator _eventAggregator;
RelayCommand _loginCommand;
private readonly UserProfileRepository _userProfileRepository;
public event EventHandler RequestClose;
public ICommand LoginCommand
{
get
{
if (_loginCommand == null)
{
_loginCommand = new RelayCommand(
param => this.Login(),
param => this.IsValid());
}
return _loginCommand;
}
}
public LoginViewModel(IEventAggregator eventAggregator, UserProfileRepository userProfileRepository, ILoginView view)
{
this._eventAggregator = eventAggregator;
this._userProfileRepository = userProfileRepository;
this.View = view;
}
#region ILoginViewModel Members
public ILoginView View { get; private set; }
#endregion
}
嗨,谢谢,我已经经历过了。但是Josh的文章没有使用CompositeWPF,所以我想知道如何实现这样一个事件处理程序,并将其与复合WPF的Regions和Bootstrapper相结合。您可以使用该代码,而不是window.Close()作为处理程序,您可以使用regionMananger.Regions[“MyRegion”].Remove(window)@Anderson,参考您之前的评论,我不明白,我应该在哪里叫regionManager.Regions[]。。。从…起这是视图背后的代码吗?@Shimmy:这要看情况了。它将位于对区域中对象的引用所在的任何位置。如果区域中存在视图,则该视图可能来自codebehind,但如果您在viewmodel中有对该视图的引用(有些人这样做),则该视图可能位于视图模型中。如果是区域中的ViewModel,而您只是在视图中进行数据模板化,那么您可以从ViewModel中执行所有这些操作,并使用.Remove(此)。这取决于你的情况。谢谢。我想我明白了。但我被困在了从模块解析控制器接口的地方。我得到一个堆栈溢出异常。LoginController controller=this.container.Resolve();抛出一个错误。有什么建议吗?听起来您的unity容器存在一些循环依赖项和/或配置不正确。我将遵循所有构造函数,并确保每个注入的参数看起来都是正确的。如果你可以尝试粘贴容器设置代码和一些类构造函数。嗨,请检查我粘贴的代码作为这个问题的答案。再次感谢。你的建议奏效了。我的视图构造函数参数错误,引发堆栈溢出异常。我修复了这些问题,它也能正常工作。有了会员们的宝贵意见,我成功地编写了代码。实现的示例类作为这个问题的答案发布。
public class LoginViewModel : ViewModelBase, ILoginViewModel
{
IEventAggregator _eventAggregator;
RelayCommand _loginCommand;
private readonly UserProfileRepository _userProfileRepository;
public event EventHandler RequestClose;
public ICommand LoginCommand
{
get
{
if (_loginCommand == null)
{
_loginCommand = new RelayCommand(
param => this.Login(),
param => this.IsValid());
}
return _loginCommand;
}
}
public LoginViewModel(IEventAggregator eventAggregator, UserProfileRepository userProfileRepository, ILoginView view)
{
this._eventAggregator = eventAggregator;
this._userProfileRepository = userProfileRepository;
this.View = view;
}
#region ILoginViewModel Members
public ILoginView View { get; private set; }
#endregion
}