使用MVVM Pattern C#Windows 8.1在页面之间导航

时间:2013-10-15 14:51:13

标签: c# xaml mvvm windows-8 windows-8.1

我试图在我的Windows 8.1商店应用中的页面之间导航。我真的很接近解决方案,但无法找到能使其发挥作用的特定部分。我能够将所有不必要的数据推送到我的下一个视图,但我无法返回。

在我的导航结构中看起来有些不对劲,但我无法弄清楚是什么。

我的MainPage.xaml看起来像这样:

<common:LayoutAwarePage
x:Name="PageRoot"
x:Class="SharePointNews.View.MainPage"
DataContext="{Binding Main, Source={StaticResource Locator}}"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:common="using:SharePointNews.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Page.Resources>
    <x:String x:Key="ChevronGlyph">&#xE26B;</x:String>
    <CollectionViewSource
        x:Name="GroupedItemsViewSource"
        Source="{Binding Items}"
        IsSourceGrouped="true"
        ItemsPath="Items" />
    <x:String x:Key="AppName">My Application</x:String>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid.ChildrenTransitions>
        <TransitionCollection>
            <EntranceThemeTransition />
        </TransitionCollection>
    </Grid.ChildrenTransitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="140" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <GridView
        x:Name="ItemGridView"
        AutomationProperties.AutomationId="ItemGridView"
        AutomationProperties.Name="Grouped Items"
        Grid.RowSpan="2"
        Padding="116,137,40,46"
        ItemsSource="{Binding Source={StaticResource GroupedItemsViewSource}}"
        SelectionMode="None"
        IsSwipeEnabled="false"
        IsItemClickEnabled="True">
        <GridView.ItemTemplate>
            <DataTemplate>
                <Grid HorizontalAlignment="Left" Width="310" Height="210">
                    <Border Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}">
                        <Image Source="{Binding Image, Converter={StaticResource SharePointImageConverter}}"
                               Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}" />
                    </Border>
                    <StackPanel VerticalAlignment="Bottom"
                                Background="{ThemeResource ListViewItemOverlayBackgroundThemeBrush}">
                        <TextBlock Text="{Binding Title}"
                                   Foreground="{ThemeResource ListViewItemOverlayForegroundThemeBrush}"
                                   Style="{StaticResource TitleTextBlockStyle}" Height="60" Margin="15,0,15,0" />
                    </StackPanel>
                </Grid>
            </DataTemplate>
        </GridView.ItemTemplate>
        <GridView.ItemsPanel>
            <ItemsPanelTemplate>
                <ItemsWrapGrid GroupPadding="0,0,70,0" />
            </ItemsPanelTemplate>
        </GridView.ItemsPanel>
        <GridView.GroupStyle>
            <GroupStyle>
                <GroupStyle.HeaderTemplate>
                    <DataTemplate>
                        <Grid Margin="1,0,0,6">
                            <Button x:Name="HeaderButton"
                                    Foreground="{ThemeResource ApplicationHeaderForegroundThemeBrush}"
                                    AutomationProperties.Name="Group Title"
                                    Style="{StaticResource TextBlockButtonStyle}"
                                    Click="HeaderButton_Click">
                                <StackPanel Orientation="Horizontal">
                                    <TextBlock x:Name="HeaderTitle" Text="{Binding Title}" Margin="3,-7,10,10"
                                               Style="{StaticResource SubheaderTextBlockStyle}"
                                               TextWrapping="NoWrap" />
                                    <TextBlock Text="{StaticResource ChevronGlyph}" FontFamily="Segoe UI Symbol"
                                               Margin="0,-7,0,10" Style="{StaticResource SubheaderTextBlockStyle}"
                                               TextWrapping="NoWrap" />
                                </StackPanel>
                            </Button>
                        </Grid>
                    </DataTemplate>
                </GroupStyle.HeaderTemplate>
            </GroupStyle>
        </GridView.GroupStyle>
    </GridView>

    <!--Vertical scrolling list only used when snapped-->
    <ListView
        x:Name="itemListView"
        AutomationProperties.AutomationId="ItemListView"
        AutomationProperties.Name="Grouped Items"
        Grid.Row="1"
        Visibility="Collapsed"
        Margin="0,-10,0,0"
        Padding="10,0,0,60"
        ItemsSource="{Binding Source={StaticResource GroupedItemsViewSource}}"
        ItemTemplate="{StaticResource Standard80ItemTemplate}"
        SelectionMode="None"
        IsSwipeEnabled="false"
        IsItemClickEnabled="True">
        <ListView.GroupStyle>
            <GroupStyle>
                <GroupStyle.HeaderTemplate>
                    <DataTemplate>
                        <Grid Margin="7,7,0,0">
                            <Button
                                AutomationProperties.Name="Group Title"
                                Style="{StaticResource TextPrimaryButtonStyle}"
                                Click="HeaderButton_Click">
                                <StackPanel Orientation="Horizontal">
                                    <TextBlock Text="{Binding Title}" Margin="3,-7,10,10"
                                               Style="{StaticResource GroupHeaderTextStyle}" />
                                    <TextBlock Text="{StaticResource ChevronGlyph}" FontFamily="Segoe UI Symbol"
                                               Margin="0,-7,0,10" Style="{StaticResource GroupHeaderTextStyle}" />
                                </StackPanel>
                            </Button>
                        </Grid>
                    </DataTemplate>
                </GroupStyle.HeaderTemplate>
            </GroupStyle>
        </ListView.GroupStyle>
    </ListView>

    <!-- Back button and page title -->
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Button x:Name="BackButton" Click="GoBack" IsEnabled="{Binding Frame.CanGoBack, ElementName=PageRoot}"
                Style="{StaticResource BackButtonStyle}" />
        <TextBlock x:Name="PageTitle" Text="{StaticResource AppName}" Style="{StaticResource PageHeaderTextStyle}"
                   Grid.Column="1" IsHitTestVisible="false" />
    </Grid>

    <VisualStateManager.VisualStateGroups>

        <!-- Visual states reflect the application's view state -->
        <VisualStateGroup x:Name="ApplicationViewStates">
            <VisualState x:Name="FullScreenLandscape" />
            <VisualState x:Name="Filled" />

            <!-- The entire page respects the narrower 100-pixel margin convention for portrait -->
            <VisualState x:Name="FullScreenPortrait">
                <Storyboard>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackButton"
                                                   Storyboard.TargetProperty="Style">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PortraitBackButtonStyle}" />
                    </ObjectAnimationUsingKeyFrames>

                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ItemGridView"
                                                   Storyboard.TargetProperty="Padding">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="96,137,10,56" />
                    </ObjectAnimationUsingKeyFrames>
                </Storyboard>
            </VisualState>

            <!--
                The back button and title have different styles when snapped, and the list representation is substituted
                for the grid displayed in all other view states
            -->
            <VisualState x:Name="Snapped">
                <Storyboard>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackButton"
                                                   Storyboard.TargetProperty="Style">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedBackButtonStyle}" />
                    </ObjectAnimationUsingKeyFrames>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PageTitle"
                                                   Storyboard.TargetProperty="Style">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedPageHeaderTextStyle}" />
                    </ObjectAnimationUsingKeyFrames>

                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView"
                                                   Storyboard.TargetProperty="Visibility">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="Visible" />
                    </ObjectAnimationUsingKeyFrames>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ItemGridView"
                                                   Storyboard.TargetProperty="Visibility">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed" />
                    </ObjectAnimationUsingKeyFrames>
                </Storyboard>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
</Grid>
</common:LayoutAwarePage>

我的MainPage.xaml的代码隐藏是这样的:

public sealed partial class MainPage : LayoutAwarePage
{
    public MainPage()
    {
        this.InitializeComponent();
    }

    private void HeaderButton_Click(object sender, RoutedEventArgs e)
    {
        NewsSite list = (NewsSite)(sender as FrameworkElement).DataContext;

        ((MainViewModel)DataContext).HeaderClickCommand(list);
   }
}

我的MainViewModel是这样的:

public class MainViewModel : ViewModelBase
{
    #region Fields
    private RelayCommand _headerClickCommand;
    #endregion

    #region Properties
    public IList<NewsSite> Items { get; set; }
    #endregion

    #region Public Methods
    /// <summary>
    /// Initializes a new instance of the MainViewModel class.
    /// </summary>
    public MainViewModel()
    {
        GetData();
    }

    public void HeaderClickCommand(NewsSite list)
    {
        var content = Window.Current.Content;
        var frame = content as Frame;

        if (frame != null)
        {
            frame.Navigate(typeof(GroupDetailPage), list);
        }
        Window.Current.Activate();   
    }

    public async void GetData()
    {
        GroupManager GM = new GroupManager();

        var groupsLoadTask = Task.Factory.StartNew(() => GM.GetGroups());
        Items = await groupsLoadTask.Result;

        this.RaisePropertyChanged(() => Items);
    }
    #endregion

    #region Private Methods


    #endregion
}

我的GroupDetailPage.xaml是这样的:

<common:LayoutAwarePage
x:Name="PageRoot"
x:Class="SharePointNews.View.GroupDetailPage"
DataContext="{Binding GroupDetails, Source={StaticResource Locator}}"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:SharePointNews.View"
xmlns:common="using:SharePointNews.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Page.Resources>
    <CollectionViewSource
        x:Name="ItemsViewSource"
        Source="{Binding Items}"/>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid.ChildrenTransitions>
        <TransitionCollection>
            <EntranceThemeTransition/>
        </TransitionCollection>
    </Grid.ChildrenTransitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="140"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <!-- Horizontal scrolling grid -->
    <GridView
        x:Name="ItemGridView"
        AutomationProperties.AutomationId="ItemsGridView"
        AutomationProperties.Name="Items"
        TabIndex="1"
        Grid.RowSpan="2"
        Padding="116,136,116,46"
        ItemsSource="{Binding Source={StaticResource ItemsViewSource}}"
        SelectionMode="None"
        IsSwipeEnabled="false">
        <GridView.ItemTemplate>
            <DataTemplate>
                <Grid HorizontalAlignment="Left" Width="310" Height="210">
                    <Border Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}">
                        <Image Source="{Binding Image, Converter={StaticResource SharePointImageConverter}}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/>
                    </Border>
                    <StackPanel VerticalAlignment="Bottom" Background="{ThemeResource ListViewItemOverlayBackgroundThemeBrush}">
                        <TextBlock Text="{Binding Title}" Foreground="{ThemeResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource BaseTextBlockStyle}" Height="60" Margin="15,0,15,0" FontWeight="SemiBold"/>
                    </StackPanel>
                </Grid>
            </DataTemplate>
        </GridView.ItemTemplate>
    </GridView>

    <!-- Back button and page title -->
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="120"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Button x:Name="BackButton" Margin="39,59,39,0" Command="{Binding NavigationHelper.GoBackCommand, ElementName=pageRoot}"
                    Style="{StaticResource NavigationBackButtonNormalStyle}"
                    VerticalAlignment="Top"
                    AutomationProperties.Name="Back"
                    AutomationProperties.AutomationId="BackButton"
                    AutomationProperties.ItemType="Navigation Button"/>
        <TextBlock x:Name="PageTitle" Text="{Binding GroupName}" Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1" 
                    IsHitTestVisible="false" TextWrapping="NoWrap" VerticalAlignment="Bottom" Margin="0,0,30,40"/>
    </Grid>
</Grid>
</common:LayoutAwarePage>

我的GroupDetailPage的背后是:

public sealed partial class GroupDetailPage : LayoutAwarePage
{
    private NavigationHelper navigationHelper;
    private ObservableDictionary defaultViewModel = new ObservableDictionary();

    public ObservableDictionary DefaultViewModel
    {
        get { return this.defaultViewModel; }
    }

    public NavigationHelper NavigationHelper
    {
        get { return this.navigationHelper; }
    }

    public GroupDetailPage()
    {
        this.InitializeComponent();
        this.navigationHelper = new NavigationHelper(this);
        this.navigationHelper.LoadState += navigationHelper_LoadState;
    }

    private void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
    {
        // TODO: Assign a bindable collection of items to this.DefaultViewModel["Items"]
        NewsSite group = ((NewsSite) e.NavigationParameter);
        ((GroupDetailViewModel)DataContext).GetData(group);
    }

    #region NavigationHelper registration

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        navigationHelper.OnNavigatedTo(e);
    }

    protected override void OnNavigatedFrom(NavigationEventArgs e)
    {
        navigationHelper.OnNavigatedFrom(e);
    }

    #endregion

}

最后我的GroupDetailViewModel是这样的:

public class GroupDetailViewModel : ViewModelBase
{
    #region Fields

    private NewsSite _newsSite;
    #endregion

    #region Properties
    public List<NewsItem> Items { get; set; }
    public string GroupName { get; set; }
    #endregion

    #region Public Methods
    public GroupDetailViewModel()
    {
    }

    public async void GetData(NewsSite group)
    {
        _newsSite = group;
        GroupName = _newsSite.Title;

        Items = _newsSite.Items.ToList();

        //Items = _newsSite.Items;

        this.RaisePropertyChanged(() => GroupName);
        this.RaisePropertyChanged(() => Items);
    }

    #endregion

    #region Private Methods



    #endregion
}

我希望有人可以帮助我。

1 个答案:

答案 0 :(得分:6)

经过数小时的试验和错误开发后,我终于在我的代码中发现了这个错误。

在MainPage.xaml中,我将pageRoot声明为页面名称。
在GroupDetailPage.xaml中,我还将pageRoot声明为页面名称。
因此,我覆盖了pageRoot,并且无法返回。

无论如何,对于所有读者,不要忘记给你的页面一个正确且易于理解的名字!它可以防止代码中出现故障。

干杯!

相关问题