如何在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。
那么,还有更好的解决方案吗?
好的,所以改为:
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);
};