2012-04-19 73 views
1

我有兩個應用程序,一個是主應用程序,另一個是設計器表單應用程序。將ViewModel替換爲另一個ViewModel

目前我有我的主要應用程序與棱鏡和mef工作。我的主要應用程序中的一些視圖只是數據輸入表單。我想從我的設計器表單應用程序加載數據輸入表單視圖,以便可以編輯,但爲此,我想使用不同的視圖模型進行設計。我不希望表單附加到它通常的viewmodel並嘗試獲取數據等。

如何使用MEF我將能夠提供不同的導出,以便它選擇這個而不是通常的viewmodel?理想情況下,它只會替換主應用程序視圖模型,所以它只是用它來代替。

這是我的例子來看,導入一個視圖模型

[Export("PatientDetailView")] 
[PartCreationPolicy(CreationPolicy.NonShared)] 
public partial class PatientDetailView : UserControl 
{ 
    [ImportingConstructor] 
    public PatientDetailView(PatientDetailViewModel viewModel) 
    { 
     InitializeComponent(); 

     this.DataContext = viewModel; 
    } 
} 

這裏是我的視圖模型的基礎:

[Export(typeof(PatientDetailViewModel))] 
[PartCreationPolicy(CreationPolicy.NonShared)] 
public class PatientDetailViewModel : ViewModelBase, IRegionManagerAware 
{ 
    [ImportingConstructor] 
    public PatientDetailViewModel(IEventAggregator eventAggregator, IDialogService dialogService, IRegionManager regionManager) 
     : base(eventAggregator, dialogService, regionManager) 
    { 
     //Contains Commands etc for Saving Patient Detail Record 
     //Receiving patient detail etc 
    } 

}

UPDATE:

的以上包含在患者模塊中部件。這適用於主應用程序。對於設計應用程序,我想的東西,如下面來代替上述視圖模型:

[Export(typeof(PatientDetailViewModel))] 
[PartCreationPolicy(CreationPolicy.NonShared)] 
public class PatientDetailViewModel : ViewModelBase, IRegionManagerAware 
{ 
    [ImportingConstructor] 
    public PatientDetailViewModel(IEventAggregator eventAggregator, IDialogService dialogService, IRegionManager regionManager) 
     : base(eventAggregator, dialogService, regionManager) 
    { 
     //Contains Commands etc for Designing the form 
     //No commands from the original VM so changes how it tries to work. 
    } 

}

以上工作來覆蓋我的主要應用程序的默認行爲。該VM將包含在Designer程序集或獨立的designerVMs程序集中。

回答

0

因爲這些是獨立的應用程序,並且datacontext可以是任何對象,所以解決方案可以很簡單。

視圖被更改爲按名稱導入它的datacontext。

public static class MefContracts 
{ 
    public const string PatientDetailViewModel = "PatientDetailViewModel"; 
} 

[Export("PatientDetailView")] 
[PartCreationPolicy(CreationPolicy.NonShared)] 
public partial class PatientDetailView : UserControl, IPartImportsSatisfiedNotification 
{ 
    [Import(MefContracts.PatientDetailViewModel, typeof(object)] 
    private object vm; 

    public void OnImportsSatisfied() 
    { 
    this.DataContext = vm; 
    } 


    public PatientDetailView() 
    { 
    InitializeComponent(); 
    } 
} 

,如果真能那麼這取決於你想要的應用程序只包括視圖模型,並通過名稱導出

[Export(MefContracts.PatientDetailViewModel, typeof(object)))] 
[PartCreationPolicy(CreationPolicy.NonShared)] 
public class PatientDetailViewModel : ViewModelBase, IRegionManagerAware 
{ 
    .... 
} 

更新沒有單獨的組件(這是國際海事組織仍然是最好的選擇,有在不同的程序集中使用vm是沒有問題的),你可以使用簡單的工廠來代替(取得ViewModel的方式):不用導入vm,而是導入一個可以創建vm的工廠。它創建的是一個配置值,必須在每個應用中設置不同的值。你將不得不用不同的契約導出vms,否則就沒有(簡單的)方式來區分它們。例如:

public static class MefContracts 
{ 
    public const string PatientDetailViewModelMain = "PatientDetailViewModelMain"; 
    public const string PatientDetailViewModelDesigner = "PatientDetailViewModelDesigner"; 
} 

//the main vm 
[Export(MefContracts.PatientDetailViewModelMain, typeof(object)))] 
[PartCreationPolicy(CreationPolicy.NonShared)] 
public class PatientDetailViewModel : ViewModelBase, IRegionManagerAware 
{ 
    .... 
} 

//the other vm 
[Export(MefContracts.PatientDetailViewModelDesigner, typeof(object)))] 
[PartCreationPolicy(CreationPolicy.NonShared)] 
public class OtherPatientDetailViewModel : ViewModelBase, IRegionManagerAware 
{ 
    .... 
} 

[Export("PatientDetailView")] 
[PartCreationPolicy(CreationPolicy.NonShared)] 
public partial class PatientDetailView : UserControl 
{ 
    [ImportingConstructor] 
    public PatientDetailView(PatientDetailViewModelFactory viewModelFactory) 
    { 
    InitializeComponent(); 
    this.DataContext = viewModelFactory.Create(); 
    } 
} 

[Export] 
class PatientDetailViewModelFactory 
{ 
    [Import] 
    private CompositionContainer container{ get; set; } 

    public enum AppType{ Main, Designer } 

    public AppType AppType{ get; set; } 

    public object Create() 
    { 
    return container.GetExportedValue<object>( 
     AppType == AppType.Main ? MefContracts.PatientDetailViewModelMain : 
           MefContracts.PatientDetailViewModelDesigner); 
    } 
} 
+0

好酷感謝回覆。我的問題是我不知道我只包含我想要的ViewModel。由於主要應用程序虛擬機總是出口,當我包含我的視圖的程序集。 我可以導出我的其他虛擬機在我的設計器應用程序,但然後有兩個出口,我可以用我的新出口替換此導出? – 2012-04-19 10:41:08

+0

你不能把每個虛擬機放在一個單獨的程序集中,並且每個應用程序只包含一個這樣的程序集? – stijn 2012-04-19 12:44:52

+0

不是真的,ViewModel應該在同一個程序集中與View一起使用,從來沒有在別處看過它們。它是該模塊的一部分,對於設計人員而言,在不同的組件中看起來有點不對。我認爲MEF是關於熱交換組件的。 – 2012-04-19 14:27:12

0

嘗試這樣:

創建定義您的視圖模型的接口:

public interface IPatientDetailViewModel{...} 

在您主要的應用從接口派生您的視圖模型和修改導出屬性。

[Export(typeof(IPatientDetailViewModel)] 
public class PatientDetailViewModel : ViewModelBase, 
    IRegionManagerAware, IPatientViewModel 
{ ... } 

我假設這些視圖位於共享程序集中。添加一個默認的構造函數,以您的觀點(如果不是在你的設計應用程序中使用MEF),並更改導入使用接口:

public PatientDetailView() 
{ 
    InitializeComponent(); 
} 

[ImportingConstructor] 
public PatientDetailView(IPatientDetailViewModel viewModel) 
{ 
    InitializeComponent(); 

    this.DataContext = viewModel; 
} 

現在,如果你的設計師的應用程序使用MEF可以導出不同的視圖模型在視圖的XAML中導入到使用MEF認爲

[Export(typeof(IPatientDetailViewModel)] 
public class DesignPatientDetailViewModel : ViewModelBase, IPatientViewModel 
{ ... } 

,或者如果不使用

d:DataContext="{d:DesignInstance local:DesignPatientViewModel}" 

相關問題