0

假设我有一个包含许多较小组件的组件,这些组件在初始化第一个组件之前检查先决条件。它们不相互依赖,所以我不关心顺序,希望它们同时运行。我正在使用 MEF 和 Caliburn.Micro 进行演示。

我想到了这个设置:

class Big
{
    [ImportMany]
    public IEnumerable<IBigPrerequisite> Prerequisites {get; set;}
    public void Initialize(){...}
}

interface IBigPrerequisite
{
    public bool IsBusy {...}
    public bool Allow {...}
    public void StartChecking();
}

现在我想要实现的是实现的类IBigPrerequisite可以打开一个窗口(例如“找不到文件 X - 这可能导致错误。继续?”) - 这应该是可能的。

但我只想一次只看到一个窗口。除了同步进行之外,我将如何做到这一点?

编辑 - 因为这个问题似乎太模糊了

我需要这些 Actions 专门运行后Big才会被激活。假设我们将激活逻辑切换为如下所示:

Big big; //we got this through Importing somewhere in composition
var allow = true;
var count = 0;
if(!pre.Any()) //no prerequisites, show window immediately
    windowManager.ShowWindow(big)
foreach(var pre in big.Prerequisities)
{
    pre.PropertyChanged += (s, args) => 
    {
        if(args.PropertyName == "IsBusy" && !pre.IsBusy) // if a prerequisite finished it's check
        {
            allow = allow && pre.Allow; //if one prerequisite says nay we could just return, actually...
            count++;
            if(count == big.Prerequisites.Count() && allow)
                windowManager.ShowWindow(big);
        }
    }
    pre.StartChecking();
}

现在,我明确希望实现的类IBigPrerequisite能够打开一个窗口,但如果满足所有先决条件(不需要用户交互),则不应显示任何窗口。我不想在这里为每一堂课都打开一扇窗。

我正在寻找一种方法,例如,给 IBigPrerequisite(可能无论如何都应该调用IPrerequisiteViewModel)一个属性bool RequestsWindow {get;},并且仅在 a)viewmodel 请求它并且 b)当时没有其他先决条件窗口打开时才创建视图。

注意:此处的代码仅用于说明,因为我还不确定如何实现此行为。我对这些框架(和概念)没有经验,所以如果这个问题看起来很愚蠢,请多多包涵。

4

2 回答 2

2

你在这里混合概念。

Caliburn.Micro 中的活动视图管理由 Conductor 类处理。一个 Conductor 派生的 ViewModel 可以显示大量 Screen 派生的 ViewModel(或其他导体)。可用项目存储在 Items 属性中。

您可以在“屏幕、导体和构图”中找到更好的描述

MEF 与导体和组合机制无关,尽管它可用于将项目列表传递给导体。您可以定义一个 [ImportMany] 构造函数参数或公共属性,以接收在初始化期间显示的屏幕并将它们存储在导体的 Items 属性中。

使用构造函数参数更优雅,因为您不必将项目从属性的设置器复制到 Items 属性。

最后,您不应在创建视图和视图模型时显示消息。这是应该留到后面的步骤,例如。在激活方法期间。Conductors 和 MEF 将各部分组合在一起并构建 UI。只有在组合步骤完成后才能执行操作并与用户交谈。

于 2013-07-25T13:58:03.973 回答
0

我将自己回答这个问题,详细说明我最终是如何解决这个问题的。

我做了一个LoaderViewModel : Conductor<PropertyChangedBase>.Collection.OneActive, IChild<Shell>并给了它一个Queue<PropertyChangedBase>

它具有通过遍历父属性直到到达窗口级别的 Show/HideWindow 方法。

它有QueueDequeue方法。在-Property上触发Queue时使用,如果没有或未标记为忙则调用。如果队列中有一个新项目,将激活一个新项目,然后调用,如果没有项目,它将改为调用。PropertyChangedRequestsViewDequeueActiveItemActiveItemDequeueShowWindowHideWindow

初始HideWindow是在ViewAttached-Event 中完成的,因为如果窗口被隐藏,CM 似乎有一些奇怪的行为。在这里,先决条件的并行检查开始并注册了一个类似于第一篇文章中的事件处理程序。

抱歉冗长,但代码有点冗长。如果有人想让我发布它,请写评论。

于 2013-07-29T12:16:46.967 回答