假设我有一个包含许多较小组件的组件,它们会在初始化第一个组件之前检查先决条件。他们不依赖于彼此,所以我不关心秩序,并希望他们同时运行。我正在使用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 - 这可能会导致错误。继续?”) - 这应该有可能。
但我只希望一次看到一个窗口。除了同步之外,我将如何实现这一目标?
编辑 - 因为这个问题似乎太模糊了
我需要在激活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请求它时才创建View b)当时没有其他先决条件窗口开启。
注意:此处的代码仅供参考,因为我不确定如何实现此行为。我对这些框架(和概念)没有经验,所以如果这个问题看起来很傻,请耐心等待。
答案 0 :(得分:2)
你在这里混合概念。
Caliburn.Micro中的活动视图管理由Conductor类处理。导体派生的ViewModel可以显示大量屏幕派生的ViewModel(或其他Conductors)。可用项目存储在Items属性中。
您可以在“Screens, Conductors and Composition”
找到更好的说明MEF与导体和组合机制无关,尽管它可用于将项目列表传递给指挥。您可以定义一个[ImportMany]构造函数参数或公共属性,它接收在初始化期间显示的屏幕,并将它们存储在指挥的Items属性中。
使用构造函数参数更优雅,因为您不必将项目从属性的setter复制到Items属性。
最后,在创建视图和视图模型时不应显示消息。这应该留待以后的步骤,例如。在Activate方法期间。 Conductors和MEF将零件组合在一起并构建UI。只有在合成步骤完成后才能执行操作并与用户交谈。
答案 1 :(得分:0)
我将自己回答这个问题,详细说明我最终是如何解决这个问题的。
我制作了LoaderViewModel : Conductor<PropertyChangedBase>.Collection.OneActive, IChild<Shell>
,然后给了Queue<PropertyChangedBase>
。
它具有Show / HideWindow方法,遍历Parent-Properties直到它到达Window-Level。
它有Queue
和Dequeue
方法。 Queue
在PropertyChanged
- 财产上触发时使用RequestsView
,如果没有标记Dequeue
或ActiveItem
则调用ActiveItem
很忙Dequeue
会激活一个新项目,如果队列中有一个项目,然后拨打ShowWindow
,如果没有项目,则会调用HideWindow
。
初始HideWindow
在ViewAttached
- 事件中完成,因为如果窗口被隐藏,CM似乎有一些奇怪的行为。在这里,开始并行检查先决条件,并注册一个类似于第一篇文章中的事件处理程序。
很抱歉很冗长,但代码有点冗长。如果有人要我发布,请写一条评论。