wpf - 从视图模型中的按钮单击调用第二个视图
问题描述
尝试使用 WPF 和 MVVM 设计模式完成 Castle Windsor。我的解决方案中有三个项目,即 MainView、ViewModel 和 IoCInstaller 项目。
MainView 依赖于 IoCInstaller 和 ViewModel。IoCInstaller 依赖于 ViewModel。
现在我想从 ViewModel 中的按钮单击操作调用 SecondView,但基于依赖关系,我发现它很难。我知道我的城堡温莎实施并不理想,但我没有找到任何关于理想实施方式的好的答案。任何建议都会非常有帮助。
在阅读文档并通过网络搜索后,我完成了基本的城堡实现工作,但是当涉及到 WPF 和 MVVM 时,我被卡住了。
视图模型项目
public partial class MainView : Window
{
public MainView()
{
InitializeComponent();
var iocContainer = IoCInstaller.WindsorContainer;
iocContainer.Install(new IoCInstaller());
var mainWindowViewModel = iocContainer.Resolve<IMainWindowViewModel>();
mainWindowViewModel.Initialize(iocContainer);
DataContext = mainWindowViewModel;
}
}
IoCInstaller 项目
public class IoCInstaller : IWindsorInstaller
{
private static WindsorContainer _windsorContainer;
public static WindsorContainer WindsorContainer
{
get
{
if (_windsorContainer == null)
{
_windsorContainer = new WindsorContainer();
return _windsorContainer;
}
else
{
return _windsorContainer;
}
}
}
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Castle.MicroKernel.Registration.Component.For<IViewModel>());
}
}
最后是 ViewModel 项目
public class ViewModel : INotifyPropertyChanged, IViewModel
{
public ViewModel()
{
}
public void Initialize(WindsorContainer windsorContainer)
{
Logger.Debug("Initializing main view model ");
iocContainer = windsorContainer;
}
public void MyActionForBttnClicked()
{
//invoke second view
}
//Other stuff
}
解决方案
您当前使用的方式Castle.Windsor
更像是 ServiceLocator,而不是 IOC 容器。
我建议您使用类型化工厂来解析您的类。对于工厂,您不需要 a public static WindsorContainer
,因为您只调用Resolve
一次(另请参阅Three-Calls-Pattern)。
首先使用Bootstrapper
您调用IWindsorInstaller
s 的 -Class 并注册使用TypedFactoryFacility
:
public class Bootstrapper
{
public IWindsorContainer BootstrapContainer()
{
IWindsorContainer container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
return container.Install(new IocInstaller());
}
}
您可以BootstrapContainer()
从您的MainView
或从您的App.xaml.cs
.
现在为您创建一个工厂ViewModel
:
public interface IViewModelFactory
{
IViewModel Create();
void Release(IViewModel viewModel);
}
你不需要实现这个工厂,Windsor 会为你做这件事。
您唯一需要做的就是更改IocInstaller
并注册您的IViewModelFactory
:
public class IocInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For<IViewModel>().ImplementedBy<MainWindowViewModel>().LifestyleTransient());
container.Register(Component.For<IViewModelFactory>().AsFactory());
}
}
确保您熟悉可用的Lifestyles
. 默认值是LifestyleSingleton()
您可能想要使用LifestyleTransient()
. 有关详细信息,请参阅此链接。
要创建你的ViewModel
,你可以Resolve
在你打电话给你的位置打电话Bootstrapper
并获得IViewModelFactory
:
public MainView()
{
//other stuff
Bootstrapper bootstrapper = new Bootstrapper();
IWindsorContainer container = bootstrapper.BootstrapContainer();
IViewModelFactory viewModelFactory = container.Resolve<IViewModelFactory>();
IViewModel viewModel = viewModelFactory.Create();
DataContext = viewModel;
}
如果你想从ViewModel
现在打开另一个窗口,你可以很容易地做到这一点。
首先为您的第二个视图模型创建一个工厂:
public interface ISecondViewModelFactory
{
ISecondViewModel Create();
void Release(ISecondViewModel secondViewModel);
}
然后在你的注册新类IocInstaller
:
public class IocInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
//registration for ViewModel
container.Register(Component.For<ISecondViewModel>().ImplementedBy<SecondViewModel>().LifestyleTransient());
container.Register(Component.For<ISecondViewModelFactory>().AsFactory());
}
}
ISecondViewModelFactory
现在可以将new设置为您的构造函数的参数ViewModel
:
public class ViewModel : INotifyPropertyChanged, IViewModel
{
private readonly ISecondViewModelFactory _secondViewModelFactory;
public ViewModel(ISecondViewModelFactory secondViewModelFactory)
{
_secondViewModelFactory = secondViewModelFactory;
}
}
温莎ISecondViewModelFactory
为您解决了问题,因此您不必关心它。
然后,您可以轻松地创建一个SecondViewModel
新窗口并显示一个新窗口,并将其SecondViewModel
作为您的DataContext
:
public void MyActionForBttnClicked()
{
//invoke second view
ISecondViewModel secondViewModel = _secondViewModelFactory.Create();
SecondWindow secondWindow = new SecondWindow();
secondWindow.DataContext = secondViewModel;
secondWindow.ShowDialog();
}
推荐阅读
- c++ - Openmp 多线程代码在使用多个线程时给出不同的答案
- python - 如何使用前两个字符而不是第二个和第三个字符来遍历列表,依此类推?
- django - 没有用户模型和 ORM 的 Django 登录身份验证和会话
- python - 如何在不通过类的情况下使用 QtMenu 或 QtMoseEvent
- deep-learning - PyTorch 加载中的 eval 方法
- union - 来自多个连接/工作簿的联合表
- autodesk-forge - 正确定位聚合 svf 模型
- xml - xsl - 为以前缀开头的标签创建嵌套结构
- python - 不同的行为 Anaconda 提示符与命令提示符
- javascript - 是否可以在 Javascript 中创建一个“class extends A {} instanceof A”为真的类 A?