0

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

2.然后我将Plugins的元数据(我自己定义,包括一个Plugin的一些基本描述)绑定到一个ListBox。

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

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 {...}

并使用反射创建的插件实例加载视图模型。

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

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

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

但是,在元数据属性中传递类型似乎很不优雅,而且不利于 DRY。

那么有没有更好的解决方案呢?

4

1 回答 1

1

好吧,相反:

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);
    };
于 2013-04-23T11:21:37.763 回答