简体   繁体   English

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

[英]How to activate corresponding screen in Caliburn.Micro

1.In my Silverlight project, I've got several Plugins (inheriting IPlugin and IScreen) and import them into the ShellView (main view) using MEF. 1.在我的Silverlight项目中,我有几个插件(继承IPlugin和IScreen),并使用MEF将它们导入ShellView(主视图)。

2.Then I bind the metadata (I've defined myself, including some basic descriptions of a Plugin) of Plugins to a ListBox. 2.然后,我将插件的元数据(我已经定义了自己,包括一些插件的基本描述)绑定到ListBox。

Now I want the ContentControl to load the viewmodel corresponding to the selcted plugin (PluginMetadata to be exactly) in the ListBox. 现在,我希望ContentControl加载与ListBox中选择的插件(确切地说是PluginMetadata)相对应的viewmodel。 The problem is the viewmodel has to be determined and instantiated at runtime. 问题在于必须在运行时确定并实例化视图模型。 I've searched a lot but it seems that people usually activate the viewmodel which is already determined at design time. 我进行了很多搜索,但似乎人们通常会激活在设计时已经确定的视图模型。 For example: 例如:

ActivateItem(new MyContentViewModel());

or: 要么:

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

One idea that came to my mind was to determine the type corresponding to the plugin by defining an attribute in my PluginMetadata class and use it like this: 我想到的一个想法是,通过在我的PluginMetadata类中定义一个属性来确定与插件相对应的类型,并像这样使用它:

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

And load the viewmodel with an instance of the plugin created using Reflection. 并使用使用Reflection创建的插件实例加载viewmodel。

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

or maybe I can also use binding if I add a property SelectedPluginType: 或者,如果添加属性SelectedPluginType,也可以使用绑定:

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

However, passing the type in the metadata attribute seems so ungraceful and against DRY. 但是,在元数据属性中传递类型似乎很不合常规,并且反对DRY。

So is there any better solution? 那么有什么更好的解决方案吗?

Ok so instead: 好吧,相反:

The ViewLocator exposes this delegate which you can replace with your own: 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);
    };

So I'd probably just stick this in your Bootstrapper.Configure : 所以我可能只是将其粘贴在您的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);
    };

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM