2015-01-21 7 views
0

데스크톱 응용 프로그램에 WPF/PRISM/MEF를 사용하고 있습니다.WPF, MEF, Prism - 셸에서 DataContext를 설정하는 방법

이것은 세 영역이있는 간단한 테스트 응용 프로그램입니다. 보기는 외부 모듈 에 정의되어 있습니다.

내 셸 DataContext를 설정해야합니다. 그래서 아래 그림처럼 과 같은 뷰 모델로 설정하면 애플리케이션이 제대로 작동합니다.

나는 명시 적 정의에 만족하지 않습니다. 일부 모듈을로드하고 초기화하는 동안 을 사용할 수 없으며 일부보기를 찾고 내 쉘의 DataContext 에 할당합니까? 설명서는 어디에서 찾을 수 있습니까? 개발자 안내서 (및 샘플 응용 프로그램)에이 설명서가 없으므로 입니다. 아니면 다른 사람이 제안을 했습니까?

Shell.xaml :

<Window x:Class="TestMenuTaskbarDT.Shell" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:prism="http://www.codeplex.com/prism" 

    xmlns:local_viewmodels="clr-namespace:TestMenuTaskbarModuleMain.ViewModels;assembly=TestMenuTaskbarModuleMain" 
    . . . 
> 

    <Window.InputBindings> 
    <KeyBinding Key="S" Modifiers="Control" Command="{Binding Path=CloseProjectCommand}" /> 
    <KeyBinding Key="O" Modifiers="Control" Command="{Binding Path=OpenProjectCommand}" /> 
    </Window.InputBindings> 
    <StackPanel> 
    <ItemsControl Name="MainMenuRegion" prism:RegionManager.RegionName="MainMenuRegion" /> 
    <ItemsControl Name="MainToolbarRegion" prism:RegionManager.RegionName="MainToolbarRegion" /> 
    <ItemsControl Name="MainContentRegion" prism:RegionManager.RegionName="MainContentRegion" /> 
    </StackPanel> 
    <!-- How does one set the datacontext, when it should be dynamically loaded? --> 
    <Window.DataContext> 
    <local_viewmodels:MainWindowViewModel /> 
    </Window.DataContext> 

</Window> 

(또는 ... 자원에 넣어 어떻게 든이 설정 local_viewmodels해야합니까?)

나는 다음 부트 스트 래퍼에 다음과 같은 일을 할 수 있나요? 또는 다른 기술이 모두 있습니까?

Bootstrapper.cs :이 속성을 정의한 것 내 Shell.xaml.cs에서

. . . 
class Bootstrapper : MefBootstrapper 
{ 
    . . . 
    protected override IModuleCatalog CreateModuleCatalog() 
    { 
     // All dlls are expected to reside in the same directory as the *.exe 
     return new DirectoryModuleCatalog() { ModulePath = System.AppDomain.CurrentDomain.BaseDirectory };   
    } 

    protected override void ConfigureAggregateCatalog() 
    { 
     base.ConfigureAggregateCatalog(); 
     this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(Bootstrapper).Assembly)); 
     // Module registration remains the same *IT* registers the views with the region catalog 
     this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(TestMenuTaskbarModuleMain.TestMenuTaskbarModuleMain).Assembly)); 
    } 
    . . . 

    protected override void InitializeShell() 
    { 
    base.InitializeShell(); 
    Application.Current.MainWindow = (Window)this.Shell; 
    // Is something like the following possible? 
     _MyBaseViewModel = GetAViewModelSomehowFromAModule("MyViewModelKey"); 
     Application.Current.MainWindow.DataContext = _MyBaseViewModel; 
    // 
    Application.Current.MainWindow.Show();     // Displays MainWindow 

    } 
+0

(또는 local_viewmodels ... 리소스에 넣고 어떻게 든 설정해야합니까?) View Model Locator.AutoWireViewModel – adminSoftDK

+0

멋진 팁 - 확장 필요 어휘. 검색 ViewModelLocator AutoWire는 Silverlight 또는 .net 4.5 또는 Prism 5.0에서 사용할 수있는 다양한 솔루션을 제공합니다. (그들은 CompositionIntializer/ExportFactory가 필요해 보입니다) 새로운 ViewLocator는 내가 원하는 것처럼 보입니다. 거의 모든 것을 XAML에서 가능하게 할 것입니다 - 현재 VS2010, .Net 4.0, Prism 4.1을 데스크톱에서만 사용하고 있습니다. 나는 구식의 것을 더 찾을 것이다. 그러나 여전히 팁을 사용할 수있다. – infowanna

+1

쉘에서 의존성 주입으로 뷰 모델을 가져올 수도 있습니다. 예를 들어'[ImportingConstructor] public Shell (MyViewModel viewModel) {this.DataContext = viewModel; }' – dymanoid

답변

1

:

[Import] 
ShellViewModel ViewModel 
{ 
    set 
    { 
     this.DataContext = value; 
    } 
} 

그리고 내 ShellViewModel 클래스의 생성자는 다음과 같이 장식 할 것 ...

[Export] 
public class ShellViewModel 

따라서 MEF 구성 가져 오기/내보내기 특성을 사용하여 DataContext setti ng. 이것은 단순화 된 예이지만 복합성 복합성 오류 등을 자세히 살펴보고 싶을 수도 있습니다. 내가 Dynamoid을 이해한다면

+0

이 기능은 런타임에 정상적으로 작동합니다. 디자인 타임에 DesignTime 속성으로 표시 할 항목을 얻을 수 있지만 모든 항목 (예 : 아이콘 및 명시 적 컨트롤)은 표시 할 수 없습니다. 그 물건을 일하게하는 것은 다른 질문입니다. 이미 물어 본 적이 없습니까? 누군가 알고 있습니까? – infowanna

+2

@infowanna, 그건 해결책이지만, 주입 된 의존성을 (ImportingConstructorAttribute'를 사용하여) 매개 변수로 더 잘 정의하는 것이 좋습니다. 의존성이 필드 나 속성을 통해 정의 된 코드를 테스트하기 란 어렵습니다. – dymanoid

0

, 나는 다음을 사용한다 :

namespace TestMenuTaskbarDT 
{  
    [Export] 
    public partial class Shell : Window 
    { 
    [ImportingConstructor] public Shell([Import("ShellViewModel")]object aShellViewModel) 
    { 
     InitializeComponent(); 
     //NOTE: DataContext is magically set from the imported object "aShellViewModel." 
     // I assume MEF uses Reflection to magically resolve all internal references. 
     DataContext = aShellViewModel; 
    } 

    /* removed, ImportingConstructor does it all in one step. 
    Note: DataContext is magically set from "value." 
    [Import("ShellViewModel")] 
    public object ViewModel 
    { 
     set { this.DataContext = value; } 
    } 
    */ 
} 

}

은 분명히 초기화 한 단계 건설 후 초기화 첫번째 구조의 2 단계 형태보다 간단하다. (사람들은 다이나모이드에 대한 코멘트를 클릭해야한다. 그의 힌트뿐만 아니라 그의 지적을 얻기위한 그의 친절한 끈기도있다.)

(여기서 남은 유일한 것은 디자인 타임 - 그러나 그것은 다른 혼란입니다.)