use*_*155 1 wpf castle-windsor castle mvvm
编辑:
我找到了一种方法来做到这一点,但我不确定它是否是最好的方法.
在WindsorContainer初始化中,首先注册viewmodel:
container.Register(Component.For<CentrosViewModel>().LifeStyle.Transient);
Run Code Online (Sandbox Code Playgroud)
后来我注册了View
container.Register(Component.For<CentrosAdminView>().LifeStyle.Transient.DependsOn(Property.ForKey("DataContext")
.Eq(ViewModelLocator.Centrosviewmodel)));
Run Code Online (Sandbox Code Playgroud)
财产的定义ViewModelLocator.Centrosviewmodel是:
public static CentrosModel Centrosviewmodel
{
get
{
return App.container.Resolve<CentrosViewModel>();
}
}
Run Code Online (Sandbox Code Playgroud)
结束编辑
我正在尝试使用Castle Windsor和Mvvm Toolkit(galasoft)创建一个Wpf应用程序,但我认为我的问题与任何MVVM工具包都是一样的.
使用MVVM,您必须将View的DataContext设置为ViewModel.通常,这是在视图声明中通过类似的方式完成的
DataContext={Binding MyViewModelInstanceName,Source={StaticResource Locator}}
Run Code Online (Sandbox Code Playgroud)
资源定位器在App.xaml中定义如下:
<Application.Resources>
<!--Global View Model Locator-->
<vm:ViewModelLocator x:Key="Locator" />
</Application.Resources>
Run Code Online (Sandbox Code Playgroud)
如果我在App.xaml中建立StartupURI到我的视图,那一切都是正确的.但是,如果我将StartupUri留空并尝试使用以下语法通过城堡获取我的视图实例:
container.Resolve<CentrosAdminView>().Show();
Run Code Online (Sandbox Code Playgroud)
我得到例外: "Cannot Find Resource with Name '{Locator}'
我认为,直接运行时的Initial DataContext与通过Castle Windsor运行时不同,这就是它无法找到资源的原因.
我的两个问题是:
我留下了我的城堡配置.任何帮助将非常感激.
我的Windsor配置如下所示:
<castle>
<properties>
<!-- SQL Server settings -->
<connectionString>Server=192.168.69.69;Database=GIOFACTMVVM;user id=sa;password=22336655</connectionString>
<nhibernateDriver>NHibernate.Driver.SqlClientDriver</nhibernateDriver>
<nhibernateDialect>NHibernate.Dialect.MsSql2005Dialect</nhibernateDialect>
</properties>
<facilities>
<facility id="nhibernatefacility"
type="Repository.Infrastructure.ContextualNHibernateFacility, Repository">
<factory id="sessionFactory1">
<settings>
<item key="connection.provider">NHibernate.Connection.DriverConnectionProvider</item>
<item key="connection.driver_class">#{nhibernateDriver}</item>
<item key="connection.connection_string">#{connectionString}</item>
<item key="dialect">#{nhibernateDialect}</item>
<item key="proxyfactory.factory_class">NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</item>
</settings>
<assemblies>
<assembly>Domain</assembly>
<assembly>ObservableCollections</assembly>
</assemblies>
</factory>
</facility>
</facilities>
</castle>
Run Code Online (Sandbox Code Playgroud)
并通过代码:
public static IWindsorContainer Start()
{
var container = new WindsorContainer(new XmlInterpreter());
container.AddFacility<TransactionFacility>();
container.Register(
Component.For<HistoriasAdminView>().LifeStyle.Transient,
Component.For<HistoriasModel>().LifeStyle.Transient,
Component.For<CentrosModel>().LifeStyle.Transient,
Component.For<CentrosAdminView>().LifeStyle.Transient,
Component.For<MainViewModel>().LifeStyle.Transient,
Component.For<MainWindow>().LifeStyle.Transient,
Component.For<IRepository<Historias>>().ImplementedBy<Repository<Historias>>().LifeStyle.Transient,
Component.For<IRepository<Centros>>().ImplementedBy<Repository<Centros>>().LifeStyle.Transient,
Component.For<IUnitOfWork>().ImplementedBy<NHUnitOfWork>().LifeStyle.Transient
);
return container;
}
Run Code Online (Sandbox Code Playgroud)
您正在使用服务定位器模式,您在其中注册服务,传递对容器的引用,并显式调用解析您的代码.如果您快速浏览Castle Windsor wiki,他们不鼓励使用容器.
通常,您应该注册所有类型(通过安装程序),只解析一个根对象(可能是您的主视图,可能是某种启动/ MVC控制器样式代码),然后由容器解析其余的.container.Dispose当您的应用程序退出时,下次您将调用容器时几乎总是这样.
有关Three Calls Pattern的信息,请参阅Windsor wiki页面.
如果您发现需要在运行时从容器中提取以创建特定实例(必须传递特定参数以创建该实例)的情况,请使用Typed Factory Facility而不是直接解析依赖关系.
MVVM与Windsor:
在我第一次使用Windsor编写的MVVM应用程序中(刚刚完成第一个版本),我只是注册了我的主视图并查看模型而没有指定生活方式.这使他们成为单身人士.
该视图将视图模型实例作为必需的依赖项(在构造函数中),并使用它来设置数据上下文.我在代码隐藏中做到了这一点,因为它是非侵入性和无痛的.
// In my program I used interfaces for everything. You don't actually have to...
public interface IMainView
{
void Show();
}
public class MainView : Window, IMainView
{
public MainView(IMainViewModel viewModel)
{
Initialize();
this.DataContext = viewModel;
}
}
public interface IMainViewModel
{
int SomeProperty { get; set; }
ICommand ShowSubViewCommand { get; }
// ...
}
public class MainViewModel : IMainViewModel
{
public MainViewModel(SomeOtherSubComponent subComponent)
{
this.subComponent = subComponent;
// ...
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
在我想要创建多个实例的子视图的地方,我用瞬态生命周期注册了它们.然后我创建了一个视图工厂和视图模型工厂,并使用它们从父视图中获取子视图和子视图模型的实例.我为视图的close事件注册了一个事件处理程序,并Release在工厂类上调用了一个方法.
public interface ISubView
{
void Show();
event Action OnDismissed;
}
public class SubView : Window, ISubView
{
public SubView(ISubViewModel viewModel)
{
Initialize();
this.DataContext = viewModel;
// Would do this in the view model,
// but it is a pain to get Window.Close to call an ICommand, ala MVVM
this.OnClose += (s, a) => RaiseDismissed();
}
public event Action OnDismissed;
private void RaiseDismissed()
{
if(OnDismissed != null)
OnDismissed();
}
}
public interface ISubViewModel
{
string SomeProperty { get; }
// ...
}
// Need to create instances on the fly, so using Typed Factory facility.
// The facility implements them, so we don't have to :)
public interface IViewFactory
{
ISubView GetSubView(ISubViewModel viewModel);
void Release(ISubView view);
}
public interface IViewModelFactory
{
ISubViewModel GetSubViewModel();
void Release(ISubViewModel viewModel);
}
// Editing the earlier class for an example...
public class MainViewModel : IMainViewModel
{
public MainViewModel(IViewFactory viewFactory, IViewModelFactory viewModelFactory)
{
this.viewFactory = viewFactory;
this.viewModelFactory = viewModelFactory;
// Todo: Wire up ShowSubViewCommand to call CreateSubView here in ctor
}
public ICommand ShowSubViewCommand { get; private set; }
private void CreateSubView()
{
var viewModel = viewModelFactory.GetSubViewModel();
var view = viewFactory.GetSubView(viewModel);
view.OnDismissed += () =>
{
viewModelFactory.Release(viewModel);
viewFactory.Release(view);
};
view.Show();
}
// Other code, private state, etc...
}
Run Code Online (Sandbox Code Playgroud)
在所有这些结束时,对容器的唯一调用是:
void App_Startup()
{
this.container = new WindsorContainer();
container.Install(Configuration.FromAppConfig());
var mainView = container.Resolve<IMainView>();
mainView.Show();
}
public override OnExit()
{
container.Dispose();
}
Run Code Online (Sandbox Code Playgroud)
所有这些严苛的好处是它独立于容器(并且可以在没有容器的情况下使用),很明显我的每个组件都依赖于哪些依赖项,并且我的大多数代码都不需要询问它的依赖性. .依赖关系只是在需要时传递给每个组件.
| 归档时间: |
|
| 查看次数: |
4296 次 |
| 最近记录: |