2013-03-08 28 views
6

Zaten bazı öğreticiler aradı ve hatta çoğul görünüyor PRISM Giriş. Ancak, çoğu örnek, birleşik kapların kullanımına ve bu özelliği Mef konteyner ile nasıl uygulayacağına dair bilgi eksikliğine dayanmaktadır. Basit helloworld modülüm web tutorial dayanmaktadır.Görüntüleme, UI'ye PRISM ve MEF kullanarak nasıl enjekte edilir?

benim bakış modeliyle benim görünümünü nasıl başlatıldığını ana benim sorunum: Sadece HelloModule ve öğretici olarak MEF değil Unity üzerinden sıkışıp kaldım hariç Benim kod gösterir aynıdır. Bu nasıl

Ancak
[ModuleExport(typeof(HelloModule), InitializationMode=InitializationMode.WhenAvailable)] 
    public class HelloModule : IModule 
    { 
     IRegionManager _regionManager; 

     [ImportingConstructor] 
     public HelloModule(IRegionManager regionManager) 
     { 
      _regionManager = regionManager; 
     } 

     public void Initialize() 
     { 
      _regionManager.Regions[RegionNames.ContentRegion].Add(ServiceLocator.Current.GetInstance<HelloView>()); 
     } 
    } 

, birisi doğru yolunu söyleyebilir:

HelloView.xaml.cs 
namespace Hello.View 
{ 
    [Export] 
    public partial class HelloView : UserControl, IHelloView 
    { 
     public HelloView() 
     { 
      InitializeComponent(); 
      Model = new HelloViewModel(this); 
     } 

     public IHelloViewModel Model 
     { 
      //get { return DataContext as IHelloViewModel; } 
      get { return (IHelloViewModel)DataContext; } 
      set { DataContext = value; } 
     } 
    } 
} 

Ve standart modül başlatma kodu: Ben deney yoluyla bulduk tek çalışan yolu Görünüm kurucusundaki görünümü-modeli başlatmak etmektir şeyler, bu Modül başlatma bölümünde yapılmalıdır.

+0

initialize görünümü modeli iyi bir yoldur. bunun gibi bir problemin var mı? – thumbmunkeys

+0

Unity ile, görünüm modelini kapsayıcılarla başlatır. Beni mefte eşdeğer bir şekilde araştırıyor? Ama eğer iyi bir şekilde söylersen, çok fazla yapışmayacağım, teşekkürler. – user2147528

cevap

1

Eğer HelloView uygulanan yolu View bazı senaryolarda gayet IHelloViewModel tam uygulanmasını bilmek zorunda olduğu anlamına gelir, ama bu interface gerek olmazdı demektir.

Sağladığım örnekler için property injection kullanıyorum, ancak constructor injection da iyi olurdu. Eğer interface kullanmak istiyorsanız

bunu şöyle uygulayabilirsiniz: Aksi

[Export(typeof(IHelloView)] 
public partial class HelloView : UserControl, IHelloView 
{ 
    public HelloView() 
    { 
     InitializeComponent(); 
    } 

    [Import] 
    public IHelloViewModel Model 
    { 
     get { return DataContext as IHelloViewModel; } 
     set { DataContext = value; } 
    } 
} 

[Export(typeof(IHelloViewModel))] 
public class HelloViewModel : IHelloViewModel 
{ 
} 

bu şekilde görünecektir:

[Export(typeof(IHelloView)] 
public partial class HelloView : UserControl, IHelloView 
{ 
    public HelloView() 
    { 
     InitializeComponent(); 
    } 

    [Import] 
    public HelloViewModel Model 
    { 
     get { return DataContext as HelloViewModel; } 
     set { DataContext = value; } 
    } 
} 

[Export] 
public class HelloViewModel 
{ 
} 

Bir şey daha: sen istemiyorsan Views'u değiştirin veya birkaç uygulama sunun, onlar için interface'a ihtiyacınız yoktur.

11

MatthiasG, MEF'deki modülleri tanımlama yolunu gösterir. Görünümün kendisi IModule uygulanmadığını unutmayın. Ancak, MEF'i PRISM ile kullanmanın ilginç kısmı, başlangıçta modüllerin UI'nize nasıl aktarılacağıdır.

Sadece burada prensipte sistemi açıklayabilir, ama doğru yönde bir işaret olabilir. Orada her şey için çok sayıda yaklaşımlar her zaman vardır, ancak bu ben en iyi uygulama olduğu anlaşılan budur ve ne çok iyi deneyimler yaptık:

Bootstrapping Prism ve Unity gibi

, hepsi ile başlar MefBootstrapper'dan Microsoft.Practices.Prism.MefExtensions'dan türetilen Bootstrapper. Önyükleyici MEF konteynırını kurar ve böylece servisler, görünümler, ViewModeller ve modeller de dahil olmak üzere her türlü ithalatı yapar.

İhracat Görünümler (modüller)

Bu MatthiasG bahsediyor parçasıdır.[Export(typeof(MyModel)] özelliğini kullanarak,

  • onun somut türü olarak modeli ihracatı kendisini (çok iyi bir arayüz MatthiasG görebilir): My uygulama GUI modülleri için aşağıdaki yapıdır. Yalnızca bir örneğin oluşturulduğunu belirtmek için [PartCreationPolicy(CreationPolicy.Shared)] ile işaretleyin (tekil davranış).

  • ViewModel sadece modeli gibi somut türü olarak kendini ihraç ve yapıcı enjeksiyon yoluyla Model alır:

    [ImportingConstructor] genel sınıf MyViewModel (MyModel modeli) { _model = Model; }

  • Görüntüle yapıcı enjeksiyon yoluyla ViewModel ithal, aynı şekilde ViewModel Model

  • ithal Ve şimdi, bu önemli: türetilmiştir belirli bir özellik, Manzara ihracatı kendisini 'standart' [Export] özniteliği. İşte bir örnek: o [Export] özelliğinden kaynaklanmaktadır olduğundan, Görünüm ithal etmek MEF kabı söyler:

[ViewExport(RegionName = RegionNames.DataStorageRegion)] 
public partial class DataStorageView 
{ 
    [ImportingConstructor] 
    public DataStorageView(DataStorageViewModel viewModel) 
    { 
     InitializeComponent(); 
     DataContext = viewModel; 
    } 
} 

[ViewExport] [ViewExport] nitelik iki şey yapar

bağlıyor. Ne gibi? Bu en Definition gizli: yapıcı imza şöyle görünür:

public ViewExportAttribute() : base(typeof(UserControl)) {} 

UserControl türüne [Export] yapıcısı arayarak, her görünüm MEF kapta UserControl olarak tescil alır. İkincisi, daha sonra Shell UI'nizin hangi Bölgeye takıldığına karar vermek için kullanılacak bir RegionName mülkünü tanımlar. RegionName özelliği, IViewRegionRegistration arabiriminin tek üyedir. nitelik sınıfı: AutoPopulateExportedViews davranış: Görüntüleme

İçe

/// <summary> 
/// Marks a UserControl for exporting it to a region with a specified name 
/// </summary> 
[Export(typeof(IViewRegionRegistration))] 
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] 
[MetadataAttribute] 
public sealed class ViewExportAttribute : ExportAttribute, IViewRegionRegistration 
{ 
    public ViewExportAttribute() : base(typeof(UserControl)) {} 

    /// <summary> 
    /// Name of the region to export the View to 
    /// </summary> 
    public string RegionName { get; set; } 
} 

Şimdi, sistemin son önemli kısmı kabuğundan bölgelere takmak bir davranış vardır. Bu, bu çizgi ile MEF kaptan senin modülünün tüm ithal: bunlar IViewRegionRegistration uygulayan bir meta veri niteliği, varsa

[ImportMany] 
private Lazy<UserControl, IViewRegionRegistration>[] _registeredViews; 

Bu, kaptan UserControl olarak tescil her türlü ithal ediyor. [ViewExport] özniteliğinizin anlamı, bu, [ViewExport(...)] ile işaretlenmiş her tür içe aktardığınız anlamına gelir.

/// <summary> 
/// A behavior to add Views to specified regions, if the View has been exported (MEF) and provides metadata 
/// of the type IViewRegionRegistration. 
/// </summary> 
[Export(typeof(AutoPopulateExportedViewsBehavior))] 
[PartCreationPolicy(CreationPolicy.NonShared)] 
public class AutoPopulateExportedViewsBehavior : RegionBehavior, IPartImportsSatisfiedNotification 
{ 
    protected override void OnAttach() 
    { 
     AddRegisteredViews(); 
    } 

    public void OnImportsSatisfied() 
    { 
     AddRegisteredViews(); 
    } 

    /// <summary> 
    /// Add View to region if requirements are met 
    /// </summary> 
    private void AddRegisteredViews() 
    { 
     if (Region == null) return; 

     foreach (var view in _registeredViews 
      .Where(v => v.Metadata.RegionName == Region.Name) 
      .Select(v => v.Value) 
      .Where(v => !Region.Views.Contains(v))) 
      Region.Add(view); 

    } 

    [ImportMany()] 
    private Lazy<UserControl, IViewRegionRegistration>[] _registeredViews; 
} 

Bildirim .Where(v => v.Metadata.RegionName == Region.Name):

Son adım bu OnAttach() mülkü içinde bahvior gösterdiği bölgelere içine Görüntüleme, takmaktır.Bu, yalnızca belirli bölge için dışa aktarılan Görünümleri almak için özniteliğin RegionName özelliğini kullanır, davranışı ekliyorsunuz. Biz tam daire, bu size şeyler MEF ile yerine düşmek nasıl bir fikir alır ve umut geldim

protected override IRegionBehaviorFactory ConfigureDefaultRegionBehaviors() 
{ 
    ViewModelInjectionBehavior.RegionsToAttachTo.Add(RegionNames.ElementViewRegion); 

    var behaviorFactory = base.ConfigureDefaultRegionBehaviors(); 
    behaviorFactory.AddIfMissing("AutoPopulateExportedViewsBehavior", typeof(AutoPopulateExportedViewsBehavior)); 
} 

:

davranış Önyükleyici içinde kabuğundan bölgelere bağlanmıştır alır PRİZMA.

Ve hala sıkılmış değilseniz, Bu mükemmel: Görünüm yapıcısı içinde

Mike Taulty's screencast

+0

Merhaba Marc, harika bir şeyler yaz. Sadece MEF ve PRISM ile çalışmaya başladım ve dürüst olmak gerekirse tamamen kayboluyorum. Tüm bunlara yol açan iyi bir temel öğretici bulamıyorum, MSDN sadece bitleri ve parçaları kapsar ve örnek projeler neye baktığımı bilmeden takip etmem için çok karmaşıktır. MEF ve PRISM ile ilgili iyi eğitimler biliyor musunuz? – NZJames

+0

@ user1122909 Onun için harika. Mike Taulty's Screencast'a baktınız mı? Birkaç saat al ve gerçekten çok öğreneceksin. Temel olarak PRISM/MEF'i bu videolarla ve başka hiçbir şeyle öğrenmedim. PRISM kılavuzu da bir arama olabilir, ama ben burada çok yüksek beklentiler olmazdı ... – Marc

+0

Hayır, şimdi bir bakalım, çok teşekkürler. Sadece bu zaman zarfında, gönderdiğim bir soru hakkında herhangi bir fikrin olduğunu düşünmüyorum: MEF/Prism? http://stackoverflow.com/questions/19526287/wpf-mef-prism-initial-region-loading – NZJames