Mvvm 在WinRT中使用多个ViewModel

Mvvm 在WinRT中使用多个ViewModel,mvvm,windows-runtime,Mvvm,Windows Runtime,操作系统:Windows 8.1 IDE:VS 2013 Express for Windows 项目:环球 目标:Windows 8.1、Phone 8.1 IoC:MEF 我的Windows应用程序基于Windows开发中心的此指南。我正在使用MEF将ViewModels注入到视图中 主页在.Shared项目中,HubPage、ItemPage和SectionPage在透视窗口和电话项目中 每个页面都有自己的ViewModel,位于名为UILogic的程序集中。在启动期间,所有视图模型都成功

操作系统:Windows 8.1 IDE:VS 2013 Express for Windows 项目:环球 目标:Windows 8.1、Phone 8.1 IoC:MEF

我的Windows应用程序基于Windows开发中心的此指南。我正在使用MEF将ViewModels注入到视图中

主页在.Shared项目中,HubPage、ItemPage和SectionPage在透视窗口和电话项目中

每个页面都有自己的ViewModel,位于名为UILogic的程序集中。在启动期间,所有视图模型都成功地注入到这些视图中。但是,通过查看即时窗口,我发现以下绑定错误:

Windows 8.1

主页面如下所示:

<Grid x:Name="LayoutRoot" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Frame x:Name="rootFrame"/>
这就是我在创业期间所做的:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
...
..
<Hub >
    <interactivity:Interaction.Behaviors>
        <core:EventTriggerBehavior EventName="SectionHeaderClick">
            <core:InvokeCommandAction Command="{Binding HubSectionHeaderCommand}"/>
        </core:EventTriggerBehavior>
    </interactivity:Interaction.Behaviors>
    <Hub.Header>
        <!-- Back button and page title -->
        <Grid>
            ...
            ..
            <Button  x:Name="backButton" Style="{StaticResource NavigationBackButtonNormalStyle}"
                Margin="0,0,39,0" 
                VerticalAlignment="Top"
                Command="{Binding NavigationHelper.GoBackCommand, ElementName=pageRoot}"
                AutomationProperties.Name="Back"
                AutomationProperties.AutomationId="BackButton"
                AutomationProperties.ItemType="Navigation Button"/>
            ...
            ..
        </Grid>
    </Hub.Header>
    ...
    ..
    <HubSection IsHeaderInteractive="True" 
                DataContext="{Binding Section3Items}" 
                d:DataContext="{Binding Groups[3], Source={d:DesignData Source=../NathsarTS.Shared/DataModel/SampleData.json, Type=data:SampleDataSource}}"
                x:Uid="Section3Header" Header="Section 3" Padding="40,40,40,32">
        <DataTemplate>
            <GridView
                x:Name="itemGridView"
                ItemsSource="{Binding Items}"
                Margin="-9,-14,0,0"
                AutomationProperties.AutomationId="ItemGridView"
                AutomationProperties.Name="Items In Group"
                ItemTemplate="{StaticResource Standard310x260ItemTemplate}"
                SelectionMode="None"
                IsSwipeEnabled="false"
                IsItemClickEnabled="True">
                <interactivity:Interaction.Behaviors>
                    <core:EventTriggerBehavior EventName="ItemClick">
                        <core:InvokeCommandAction Command="{Binding HubSectionGridItemCommand}"/>
                    </core:EventTriggerBehavior>
                </interactivity:Interaction.Behaviors>
            </GridView>
        </DataTemplate>
    </HubSection>
    ...
    ..
</Hub>
protected override async void OnLaunched(LaunchActivatedEventArgs args)
{
    this._configuration.WithAssembly(typeof(App).GetTypeInfo().Assembly)
        .WithAssembly(typeof(NathsarTS.UILogic.UILogicBusinessLogic).GetTypeInfo().Assembly)
        .WithAssembly(typeof(NathsarTS.Common.CommonBusinessLogic).GetTypeInfo().Assembly)
        .WithAssembly(typeof(NathsarTS.ODSDocuments.ODSDocumentsBusinessLogic).GetTypeInfo().Assembly);
    this._compositionHost = this._configuration.CreateContainer();

    await ShowWindow(args);
}

private async Task ShowWindow(LaunchActivatedEventArgs e)
{
    MainPage mainPage = Window.Current.Content as MainPage;
    Frame rootFrame = null;

    // Do not repeat app initialization when the Window already has content,
    // just ensure that the window is active
    if (mainPage == null)
    {
        mainPage = _compositionHost.GetExport<MainPage>();
    }

    // Retrieve the root Frame to act as the navigation context and navigate to the first page
    // Don't change the name of "rootFrame" in MainPage.xaml unless you change it here to match.
    rootFrame = (Frame)mainPage.FindName("rootFrame");
    if (rootFrame != null)
    {
        // Associate the frame with a SuspensionManager key.
        SuspensionManager.RegisterFrame(rootFrame, "AppFrame");

        // TODO: change this value to a cache size that is appropriate for your application
        rootFrame.CacheSize = 1;

        if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
        {
            // Restore the saved session state only when appropriate
            try
            {
                await SuspensionManager.RestoreAsync();
            }
            catch (SuspensionManagerException)
            {
                //Something went wrong restoring state.
                //Assume there is no state and continue
            }
        }

        // Place the main page in the current Window.
        Window.Current.Content = mainPage;

        if (rootFrame.Content == null)
        {
            // When the navigation stack isn't restored navigate to the first page,
            // configuring the new page by passing required information as a navigation
            // parameter
            HubPage hubPage = _compositionHost.GetExport<HubPage>();
            if (!rootFrame.Navigate(hubPage.GetType(), e.Arguments))
            {
                throw new Exception("Failed to create initial page");
            }
        }

    }

    // Ensure the current window is active
    Window.Current.Activate();
}

谢谢你的帮助

能够修复我的副本,并将正确的ViewModel连接到PageView。问题是1的.Navigation在MEF进行初始化后继续重新初始化页面构造函数,2由于某种原因HubPage DataContext丢失

我就是这样解决的:

protected override async Task OnLaunchApplicationAsync(LaunchActivatedEventArgs args)
{
    Debug.WriteLine("OnLaunchApplicationAsync...");

    MainPage mainPage = _compositionHost.GetExport<MainPage>();
    Window.Current.Content = mainPage;
    Frame rootFrame = (Frame)mainPage.FindName("rootFrame");

    if (rootFrame != null)
    {
        if (rootFrame.Content == null)
        {
            // When the navigation stack isn't restored navigate to the first page,
            // configuring the new page by passing required information as a navigation
            // parameter
            HubPage hubPage = _compositionHost.GetExport<HubPage>();
            rootFrame.Content = hubPage;
        }
    }

    Window.Current.Activate();
    await Task.FromResult<object>(null);
}
我没有在初始启动时使用.Navigation,而是将页面类型分配给了.Content

MainPage InitializeComponent
PropertiesService instantiation
MainPageViewModel instantiation
MainPage OnImportsSatisfied instantiation
HubPage InitializeComponent
HubPageViewModel instantiation
HubPage OnImportsSatisfied instantiation
HubPage InitializeComponent
HubPage OnNavigatedTo instantiation
protected override async void OnLaunched(LaunchActivatedEventArgs args)
{
    this._configuration.WithAssembly(typeof(App).GetTypeInfo().Assembly)
        .WithAssembly(typeof(NathsarTS.UILogic.UILogicBusinessLogic).GetTypeInfo().Assembly)
        .WithAssembly(typeof(NathsarTS.Common.CommonBusinessLogic).GetTypeInfo().Assembly)
        .WithAssembly(typeof(NathsarTS.ODSDocuments.ODSDocumentsBusinessLogic).GetTypeInfo().Assembly);
    this._compositionHost = this._configuration.CreateContainer();

    await ShowWindow(args);
}

private async Task ShowWindow(LaunchActivatedEventArgs e)
{
    MainPage mainPage = Window.Current.Content as MainPage;
    Frame rootFrame = null;

    // Do not repeat app initialization when the Window already has content,
    // just ensure that the window is active
    if (mainPage == null)
    {
        mainPage = _compositionHost.GetExport<MainPage>();
    }

    // Retrieve the root Frame to act as the navigation context and navigate to the first page
    // Don't change the name of "rootFrame" in MainPage.xaml unless you change it here to match.
    rootFrame = (Frame)mainPage.FindName("rootFrame");
    if (rootFrame != null)
    {
        // Associate the frame with a SuspensionManager key.
        SuspensionManager.RegisterFrame(rootFrame, "AppFrame");

        // TODO: change this value to a cache size that is appropriate for your application
        rootFrame.CacheSize = 1;

        if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
        {
            // Restore the saved session state only when appropriate
            try
            {
                await SuspensionManager.RestoreAsync();
            }
            catch (SuspensionManagerException)
            {
                //Something went wrong restoring state.
                //Assume there is no state and continue
            }
        }

        // Place the main page in the current Window.
        Window.Current.Content = mainPage;

        if (rootFrame.Content == null)
        {
            // When the navigation stack isn't restored navigate to the first page,
            // configuring the new page by passing required information as a navigation
            // parameter
            HubPage hubPage = _compositionHost.GetExport<HubPage>();
            if (!rootFrame.Navigate(hubPage.GetType(), e.Arguments))
            {
                throw new Exception("Failed to create initial page");
            }
        }

    }

    // Ensure the current window is active
    Window.Current.Activate();
}
protected override async Task OnLaunchApplicationAsync(LaunchActivatedEventArgs args)
{
    Debug.WriteLine("OnLaunchApplicationAsync...");

    MainPage mainPage = _compositionHost.GetExport<MainPage>();
    Window.Current.Content = mainPage;
    Frame rootFrame = (Frame)mainPage.FindName("rootFrame");

    if (rootFrame != null)
    {
        if (rootFrame.Content == null)
        {
            // When the navigation stack isn't restored navigate to the first page,
            // configuring the new page by passing required information as a navigation
            // parameter
            HubPage hubPage = _compositionHost.GetExport<HubPage>();
            rootFrame.Content = hubPage;
        }
    }

    Window.Current.Activate();
    await Task.FromResult<object>(null);
}