Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Wpf Prism2/MVVM从ViewModel关闭视图_Wpf_Mvvm_Prism - Fatal编程技术网

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
}