Prism2/MVVM 从 ViewModel 关闭视图

发布于 2024-08-04 19:02:56 字数 135 浏览 1 评论 0原文

如何从 ViewModel 中关闭视图?

我有一个 WPF 窗口,它定义了多个区域并用作 Shell 来托管我的应用程序的视图。我希望有一个视图能够将其自身从区域中删除,或者从选项卡式容器中关闭它。我如何从 ViewModel 完成此行为。

How do I close a View from its ViewModel?

I've a WPF window which has defined multiple Regions and being used as a Shell to host views for my application. I would like to have a View able to remove itself from the Region, or close it from a tabbed container. How can I accomplish this behavior from ViewModel.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

峩卟喜欢 2024-08-11 19:02:56

由于您的 ViewModel 没有(也不应该)引用 View,因此您无法直接关闭它。但是,您可以做的是在 ViewModel 中添加一个 Event 来指示它想要关闭。

Josh Smith 撰写了一篇文章,展示了如何执行此操作(关于文章读到一半)。

Since your ViewModel doesn't (and shouldn't) have a reference to the View, you can't close it directly. However, what you can do is add an Event in your ViewModel to indicate that it wants to be closed.

Josh Smith has written an article showing how to do this (about halfway through the article).

痴情 2024-08-11 19:02:56

这实际上取决于您的应用程序架构,但以下是我使用 Prism 的方法。

首先我想说,让你的虚拟机引用视图是可以的,只要它不是视图的具体实现,即通过接口引用。

我使用依赖注入将 View 和 ViewModel 结合起来,这与 StockTraderRI 中的完成方式非常相似。所以我有一个 IView 和一个 IViewModel。 IViewModel 有一个名为“View”的 IView 类型的属性。

从与您的区域配合使用的代码层(对我来说,通常是控制器...参见 StockTraderRI),添加从区域中删除视图的机制。

例如:

myRegion.Remove(myIViewModel.View);

如果区域由控制器处理,您可能希望在虚拟机上放置一个简单的事件,以在虚拟机想要“关闭”时发出通知。如果您希望使用弱事件模型,您还可以尝试使用 IEventAggregator。如果该区域是在虚拟机中处理的,只需在其中添加该代码即可。

This really depends on your app architecture, but here's how I do it with Prism.

First I want to say, it is ok to have your VM reference the View just as long as it is not a concrete implementation of the View, ie, references by interface.

I marry the View and ViewModel using dependency injection, very similar to how it's done in the StockTraderRI. So I have an IView and an IViewModel. IViewModel has a propery called "View" of type IView.

From the code layer (for me, usually the controller...see StockTraderRI) that works with your regions, add the mechanism to remove your view from the region.

For example:

myRegion.Remove(myIViewModel.View);

If regions are handled by a controller, you may want to put a simple event on the VM to notify when a VM wants to be "closed". You can also experiment with the IEventAggregator if you wish to use a weak eventing model. If the region is handled in the VM, simply add that code there.

兮子 2024-08-11 19:02:56

这是我的登录模块的样子:

    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
}

这是控制器:

    public class LoginController : ILoginController
{
    private readonly IRegionManager regionManager;
    private readonly ILoginViewModel model;

    public LoginController(IRegionManager regionManager, ILoginViewModel model)
    {
        this.regionManager = regionManager;
        this.model = model;
        model.RequestClose += new EventHandler(model_RequestClose);
    }

    void model_RequestClose(object sender, EventArgs e)
    {
        regionManager.Regions["LoginRegion"].Remove(model.View);
    }

    #region ILoginController Members

    public void Run()
    {
        // Register views here
        regionManager.Regions["LoginRegion"].Add(model.view);
    }

    #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
}

This how my Login module looks like:

    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
}

This is the controller:

    public class LoginController : ILoginController
{
    private readonly IRegionManager regionManager;
    private readonly ILoginViewModel model;

    public LoginController(IRegionManager regionManager, ILoginViewModel model)
    {
        this.regionManager = regionManager;
        this.model = model;
        model.RequestClose += new EventHandler(model_RequestClose);
    }

    void model_RequestClose(object sender, EventArgs e)
    {
        regionManager.Regions["LoginRegion"].Remove(model.View);
    }

    #region ILoginController Members

    public void Run()
    {
        // Register views here
        regionManager.Regions["LoginRegion"].Add(model.view);
    }

    #endregion
}

And this is my 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
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文