【问题标题】:Caliburn.Micro EventAggregator in ViewModels not instantiated by CMViewModel 中的 Caliburn.Micro EventAggregator 未由 CM 实例化
【发布时间】:2014-12-02 20:03:42
【问题描述】:

在我的 ShellViewModel 中,我有以下使用 Linq 和 EntityFramework 进行查询的函数。这里的目标是将 POCO 转换为 ViewModel,并使用 CM 将生成的 ViewModel 绑定到 ShellView 中的 ListBox。

下面是代码的部分列表。一切正常。但是,我现在需要每个 ItemViewModel 能够在发生特定操作时通知 ShellViewModel。如何将 CM 的 EventAggregator 放入每个 ItemViewModel?所有的 EventAggregator 示例都通过 ViewModel 的 Ctor 进行依赖注入显示了这种情况。在实例化 ViewModel 时如何使依赖注入工作,如下面的 GetData() 所示?

[Export(typeof(ShellViewModel))]
public class ShellViewModel : Conductor<object>, IHandle<UserPasswordChanged>
{
    private void GetData()
    {
        var query = _EfDataContext.Items
            .Where(x => (x.CreatedDtm > DayBeginning && x.CreatedDtm <= NowDtm));

        //Create a list of ItemViewModels for Caliburn.Micro to Bind
        //How can EventAggregator be injected into ItemViewModel when
        //creating ViewModels this way?

        this.Items = new BindableCollection<ItemViewModel>(query
                .Select(x => new ItemViewModel
                {
                    Item = x
                }));
    }
    [ImportingConstructor]
    public ShellViewModel(IEventAggregator eventAggregator)
    {
            _eventAggregator = eventAggregator;
            _eventAggregator.Subscribe(this);
            IsDeveloperMode = false;

    }
}

【问题讨论】:

    标签: wpf mvvm caliburn.micro


    【解决方案1】:

    原来问题出在我的 Linq 语句上。我已经尝试将事件聚合器从 ShellViewModel 传递到 ItemViewModel,因为正如 Sven 所指出的,事情已经被注入。为什么要再次注入?

    Items =
                new BindableCollection<ItemViewModel>(query
                    .Select(x => new ItemViewModel
                    {
                        Item = x,
                        EventAggregator = this._eventAggregator
                    }));
    

    但是,这会导致以下错误: 无法创建“Caliburn.Micro.IEventAggregator”类型的常量值。此上下文仅支持原始类型或枚举类型。

    当时我没有意识到这不是 Mef 或 CM 的问题,而是 Linq 的问题。以下两步解决方案有效:

    Items =
                new BindableCollection<ItemViewModel>(query
                    .Select(x => new ItemViewModel
                    {
                        Item = x
                    }));
    
    foreach (var itemViewModel in Items)
                itemViewModel .EventAggregator = this._eventAggregator;
    

    【讨论】:

    • 你的问题解决了吗?这是一种通过在 ViewModel 本身之外分配 EventAggregator 的奇怪方式。你可以在构造函数中执行它,例如 public ItemViewModel(IEventAggregator eventAggregator){ this.EventAggregator = evenAggregator} 而你不要 new ItemViewModel 而是让 MVVM 处理它跨度>
    【解决方案2】:

    为什么不像这样简单地传递您的 EventAggregator?

    // ...
    .Select(x => new ItemViewModel(_eventAggregator)
    // ...
    

    因为这些是由已经注入依赖项的实例显式创建的。

    【讨论】:

    • 感谢您的建议 Sven,当我使用对象初始化语法尝试此操作时,我收到以下错误:“无法创建类型为 'Caliburn.Micro.IEventAggregator' 的常量值。只有原始类型或在此上下文中支持枚举类型。"
    • 嗯,我似乎无法重现该错误消息。我尝试了 EventAggregator = this._event 就像您在自己的答案中发布的那样,但是效果很好。 EventAggregator 是 ItemViewModel 上 IEventAggregator 的属性吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-08
    相关资源
    最近更新 更多