【问题标题】:ViewModel constructor with IEventAgrrregator as argument以 IEventAgrrregator 作为参数的 ViewModel 构造函数
【发布时间】:2018-07-29 11:09:11
【问题描述】:

在我的应用程序中,我通常使用不带任何参数的 ViewModel 构造函数并从 xaml 中找到我的 ViewModel,如下所示。

<UserControl.Resources>
    <ResourceDictionary>
        <vm:TabViewModel  x:Key ="vm" ></vm:TabViewModel>
    </ResourceDictionary>
</UserControl.Resources>

通过使用它,我可以在设计时在 xaml 中轻松引用我的 ViewModel 属性。

<Grid x:Name="grid" DataContext="{Binding Source={StaticResource ResourceKey=vm}}">

但是,由于我要在两个 ViewModel 之间进行通信,所以我开始使用 Prism 6(事件聚合器)。

public TabViewModel(IEventAggregator eventAggregator)
    {
        this.eventAggregator = eventAggregator;
        tabPoco = new TabWindowPoco();

        tabPoco.Tag = "tag";
        tabPoco.Title = "Title";

        tabPoco.ListDataList = new ObservableCollection<ListData>();

        tabPoco.ListDataList.Add(new ListData() { Name = "First", Age = 10, Country = "Belgium" });
        tabPoco.ListDataList.Add(new ListData() { Name = "Second", Age = 11, Country = "USA" });
        tabPoco.ListDataList.Add(new ListData() { Name = "Third", Age = 12, Country = "France" });
    }

我正在使用 Bootstrapper 来加载应用程序。

由于我使用的是 IEventAggregator,我不得不使用 prism:ViewModelLocator.AutoWireViewModel="True" 来定位 ViewModel。否则,应用程序不会运行。现在,我无法将 ViewModel 用作资源,也无法将其附加到 DataContext。

我不希望 Prism 自动定位相应的 ViewModel,我想控制它。我想在 xaml 中找到它并将其分配给 DataContext。

有谁知道我是如何做到这一点的?

【问题讨论】:

    标签: wpf mvvm eventaggregator prism-6 viewmodellocator


    【解决方案1】:

    您似乎未能设置依赖注入容器。 Dependency injection uses a preset mapping 在接口类型和具体类型之间。您的映射将与此类似(Prism/EntLib 5 示例):

    public class Bootstrapper : UnityBootstrapper
    {
        protected override void ConfigureContainer()
        {
            base.ConfigureContainer();
    
            this.Container.RegisterType<IMyViewModel, SomeViewModel>();
            this.Container.RegisterType<IFooViewModel, SomeOtherViewModel>();
        }
    }
    

    稍后当您拨打电话时:

    this.DataContext = container.Resolve<IMyViewModel>();
    

    这比这个小例子所建议的更强大——你可以从你的容器(或区域管理器)中新建一个视图,并最终自动解决它的所有依赖关系。

    要在 XAML 中维护智能感知等,您可以在 XAML 中指定视图模型的 type

    <UserControl x:Class="YourNamespace.YourFancyView"
                 ...
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:myNamespaceAlias="clr-namespace:PathToMyViewModelsInterface" 
                 mc:Ignorable="d" 
                 d:DesignHeight="100" d:DesignWidth="100"
                 d:DataContext="{d:DesignInstance myNamespaceAlias:IMyViewModel, IsDesignTimeCreatable=False}" 
                 ...
                 >
    </UserControl>
    

    查看相关的 SO 问题 How do I specify DataContext (ViewModel) type to get design-time binding checking in XAML editor without creating a ViewModel object?Using Design-time Databinding While Developing a WPF User Control 了解更多信息。

    【讨论】:

    • 感谢 Slugster 的回复。它确实有效。我只是想知道这是否是使用 Prism for Event Aggregator 在两个 ViewModel 之间进行通信的最佳方式。如果您有更好的沟通方式,那么我也愿意研究该选项。
    • EventAggregator 绝对是最好的交流方式——它需要多几行代码,但 pub/sub 事件模型让一切变得更简洁(只是不要忘记取消订阅消息)。如果您是从容器创建视图模型,那么您只需向构造函数添加一个 IEventAggregator 参数,容器将为您解决该问题。
    • 谢谢。我一定会尝试遵循您的提示:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-26
    • 1970-01-01
    • 2013-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多