如何在Caliburn.Micro.中激活相应的屏幕

本文关键字:屏幕 激活 Caliburn Micro | 更新日期: 2023-09-27 18:10:01

1.在我的Silverlight项目中,我有几个插件(继承了IPlugin和IScreen(,并使用MEF将它们导入ShellView(主视图(。

2.然后我将插件的元数据(我已经定义了自己,包括插件的一些基本描述(绑定到ListBox。

现在,我希望ContentControl在ListBox中加载与所选插件(确切地说是PluginMetadata(相对应的视图模型。问题是必须在运行时确定并实例化视图模型。我搜索了很多,但似乎人们通常会激活在设计时已经确定的视图模型。例如:

ActivateItem(new MyContentViewModel());

或:

<ContentControl x:Name="MyContent" cal:View.Model="{Binding Path=MyContentViewModel}" />

我想到的一个想法是,通过在我的PluginMetadata类中定义一个属性来确定与插件对应的类型,并像这样使用它:

[Export(IPlugin)]
[PluginMetadata(Type=typeof(Plugin1), ...some other properties...)]
public class Plugin1 {...}

并加载带有使用Reflection创建的插件实例的视图模型。

ActivateItem(Activator.CreateInstance<SelectedPluginMetadata.Type>());

或者,如果我添加SelectedPluginType:属性,我也可以使用绑定

<ContentControl x:Name="MyContent" cal:View.Model="{Binding Path=SelectedPluginType}" />

然而,在元数据属性中传递类型似乎太不礼貌了,而且不利于DRY。

那么,还有更好的解决方案吗?

如何在Caliburn.Micro.中激活相应的屏幕

好的,所以改为:

ViewLocator公开了这个委托,您可以用自己的替代:

    public static Func<Type, DependencyObject, object, UIElement> LocateForModelType = (modelType, displayLocation, context) => {
        var viewType = LocateTypeForModelType(modelType, displayLocation, context);
        return viewType == null
                   ? new TextBlock { Text = string.Format("Cannot find view for {0}.", modelType) }
                   : GetOrCreateViewType(viewType);
    };

所以我可能会把这个放在你的Bootstrapper.Configure:里

    ViewLocator.LocateForModelType = (modelType, displayLocation, context) => 
    {
        if(modelType is IPlugin) modelType = ? // whatever reflection is necessary to get the underlying type? Just GetType()?
        var viewType = ViewLocator.LocateTypeForModelType(modelType, displayLocation, context);
        return viewType == null
                   ? new TextBlock { Text = string.Format("Cannot find view for {0}.", modelType) }
                   : ViewLocator.GetOrCreateViewType(viewType);
    };