0

enter code hereたぶん、タイトルはそれほど具体的ではありません。

私が抱えている状況はです。ItemsControlmany を挿入する場所がViewModelsあり、これはthroughItemsControlを表示する必要があります。ViewDataTemplates

だから、私はこれらを a で書きますResourceDictionary

ここに画像の説明を入力

そして、これResourceDictionaryをに追加しApplicationResourcesます。

これはとても冗長で面倒です。

私も使用しているので、MEFを使用して、対応する描画する必要があることMVVMを発見する方法ができないかと考えていました。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 に答える