gpt4 book ai didi

wpf - WPF +温莎城堡+ MVVM : Locator-DataContext

转载 作者:行者123 更新时间:2023-12-03 10:20:12 31 4
gpt4 key购买 nike

编辑:
我已经找到一种执行此操作的方法,但是我不确定这是否是最佳方法。
WindsorContainer初始化中,首先我注册viewmodel:

container.Register(Component.For<CentrosViewModel>().LifeStyle.Transient);

然后我注册 View
        container.Register(Component.For<CentrosAdminView>().LifeStyle.Transient.DependsOn(Property.ForKey("DataContext")
.Eq(ViewModelLocator.Centrosviewmodel)));

属性 ViewModelLocator.Centrosviewmodel的定义是:
    public static CentrosModel Centrosviewmodel
{
get
{
return App.container.Resolve<CentrosViewModel>();
}
}

结束编辑

我正在尝试使用CaSTLe Windsor和Mvvm Toolkit(galasoft)制作Wpf应用程序,但我想我的问题将与任何MVVM工具包相同。

使用MVVM,您必须将View的DataContext设置为ViewModel。通常,这是通过 View 声明中的类似方法完成的
DataContext={Binding MyViewModelInstanceName,Source={StaticResource Locator}}

在App.xaml中定义资源定位符,如下所示:
<Application.Resources>
<!--Global View Model Locator-->
<vm:ViewModelLocator x:Key="Locator" />
</Application.Resources>

如果我在App.xaml中建立StartupURI,则一切正常。
但是,如果我将StartupUri留空,则尝试使用以下语法通过城堡获取我的 View 实例:
container.Resolve<CentrosAdminView>().Show();

我得到异常: "Cannot Find Resource with Name '{Locator}'
我认为Initial DataContext直接运行时与通过CaSTLe Windsor运行时不同,这就是它无法找到资源的原因。

我的两个问题是:
  • 使用温莎城堡时是否必须有ViewModelLocator?在

  • 情况为"is":如何使用
  • 正确设置Views的DataContext
  • 温莎?如果没有:正确的方法是什么?

  • 我放弃了我的城堡配置。任何帮助将非常感激。

    我的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>

    并通过代码:
        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;
    }

    最佳答案

    您正在使用服务定位器模式,在该模式中注册服务,传递对容器的引用,并在所有代码中显式调用resolve。如果您快速浏览Castle Windsor wiki,他们会阻止这种容器的使用。
    通常,您应该注册所有类型(通过安装程序),仅解析一个根对象(可能是您的主 View ,也许是某种启动/MVC Controller 样式代码),然后让其余的容器解决。下次您调用应用程序时,容器将几乎总是container.Dispose
    有关the Three Calls Pattern的信息,请参见温莎Wiki页面。
    如果发现需要在运行时从容器中拉出以创建特定实例的情况(必须传递特定参数来创建该实例),请使用Typed Factory Facility而不是直接解决依赖关系。
    带有Windsor的 MVVM:
    在我用Windsor编写的第一个MVVM应用程序中(刚刚完成了第一个版本),我只是注册了主 View 和 View 模型而未指定生活方式。这默认为单例。
    该 View 将 View 模型实例作为必需的依赖项(在构造函数中),并使用它来设置数据上下文。我这样做是在代码隐藏的后面进行的,因为它是非侵入性的且无痛苦的。

    // 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;
    // ...
    }

    // ...
    }
    在要创建多个实例的 subview 中,我将它们注册为临时生命周期。然后,我创建了一个 View 工厂和 View 模型工厂,并使用它们从父 View 中获取 subview 和 subview 模型的实例。我为 View 的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...
    }
    最后,对容器的唯一调用是:
    void App_Startup()
    {
    this.container = new WindsorContainer();
    container.Install(Configuration.FromAppConfig());

    var mainView = container.Resolve<IMainView>();
    mainView.Show();
    }

    public override OnExit()
    {
    container.Dispose();
    }
    所有这些繁琐工作的好处是,它独立于容器(并且可以在不使用容器的情况下使用),很明显,我的每个组件都具有哪些依赖关系,并且我的大多数代码都不必询问其依赖关系。依赖关系仅在需要时才交给每个组件。

    关于wpf - WPF +温莎城堡+ MVVM : Locator-DataContext,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5899863/

    31 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com