0

enter code here也许标题不是那么具体。

我现在的情况是。我有一个ItemsControl我插入很多的地方ViewModels,这ItemsControl应该显示View通过DataTemplates

所以,我把这些写在ResourceDictionary

在此处输入图像描述

然后,我将它添加ResourceDictionaryApplicationResources.

这太多余了,太累了。

MVVM也在使用,所以我在想是否可以使用 MEF 来发现View应该绘制的相应内容。我正在调查创建自定义属性标签可能是简化这些冗余代码的好主意,也许在视图中添加这个标签告诉它ViewModel应该为这个视图绘制,但我迷失了 MEF。

计划是删除ResourceDictionary.

你能帮我一把吗?

提前致谢。

4

3 回答 3

2

在我的主机 WPF 应用程序中,我添加了这个导入:

[ImportMany("ApplicationResources", typeof(ResourceDictionary))]
public IEnumerable<ResourceDictionary> Views { get; set; }

ResourceDictionary 背后的代码:

[Export("ApplicationResources", typeof(ResourceDictionary))]
public partial class ItemView : ResourceDictionary 
{
    public ItemView()
    {
        InitializeComponent();
    }
}

作为参考,示例 ResourceDictionary 的 Xaml 如下所示:

<DataTemplate DataType="{x:Type local:ItemViewModel}">
    ...
</DataTemplate>

在 WPF 应用程序中,在主窗口之前:

// Add the imported resource dictionaries
// to the application resources
foreach (ResourceDictionary r in Views)
{
    this.Resources.MergedDictionaries.Add(r);
}
于 2012-08-22T20:35:21.640 回答
1
[System.ComponentModel.Composition.InheritedExport(typeof(ProblemView))]
public abstract class ProblemView : UserControl // or whatever your Views inherit
{
   public abstract Type ViewModelType { get; }
}

[System.ComponentModel.Composition.InheritedExport(typeof(ProblemViewModel))]
public abstract class ProblemViewModel : BaseViewModel // or whatever your ViewModels inherit
{
}

// in your App class
{
   [ImportMany(typeof(ProblemView))]
   public ProblemView[] Views { get; set; }
   [ImportMany(typeof(ProblemViewModel))]
   public ProblemViewModel[] ViewModels { get; set; }

   void MarryViewViewModels()
   {// called during MEF composition
      foreach (ProblemView view in Views)
      {
         foreach(ProblemViewModel vm in ViewModels)
         {
            if(Equals(view.ViewModelType, vm.GetType())
            {// match -> inject the ViewModel
               view.DataContext = vm;
               break;
            }
         }      
      }
   }
}

// example of usage
public partial class SomeView : ProblemView
{
   public override Type ViewModelType { get { return typeof(SomeViewModel); } }
}
于 2012-08-25T03:00:11.180 回答
0

让我解释一下如何设置这样的东西。您可以在官方文档中查找更多信息

最好的实现是使用接口和鸭子类型。

public interface IModule {
    DataTemplate Template { get; set; }
    string Name{get;set;}
    ...
}

然后对于每个插件,继承这个接口

[Export(typeof(IModule ))]
public class SampleModule : IModule {
    private DataTemplate template;
    public DataTemplate IModule.Template {
        get { return this.teplate; }
        set { this.template = value; }
    }

    private string name = "SamplePlugin";
    public string  IModule.Name{
        get { return this.name ; }
        set { this.name = value; }
    }

    ...
}

SampleModule 类在单独的程序集中,而 IModule 与 Application 和每个模块程序集都相同。

现在您需要加载应用程序可用的每个模块。此代码片段来自应用程序窗口

...
[ImportMany]
public IEnumerable<IModule> ModulesAvailable {get;set;}
...
public void LoadModules(string path) {
    DirectoryCatalog catalog = new DirectoryCatalog(path);
    catalog.ComposeParts(this);
}

现在您可以使用 foreach 循环并将它们添加到应用程序资源

foreach(IModule module in ModulesAvailable) {
    Application.Current.Resources.Add(module.Template, module.Name);
}

这只是概念,代码未经测试。

我在几个月前做的高中期末项目中使用了 MEF ,所以你可以看看我的代码。它是支持公式的电子表格应用程序,所有操作和操作数都作为插件加载,因此非常灵活。

于 2012-08-22T20:56:07.173 回答