[英]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.