Windows应用商店应用 - XAML - 一个滚动条上的GridView和详细信息

时间:2014-05-15 11:31:57

标签: xaml gridview windows-store-apps scrollview

我使用模板有一个标准的拆分页面,但我使用的是GridView而不是ListView

<Page
x:Name="pageRoot"
x:Class="App1.Pages.SplitPage1"
DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1.Pages"
xmlns:common="using:App1.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Page.Resources>
    <!-- Collection of items displayed by this page -->
    <CollectionViewSource
    x:Name="itemsViewSource"
    Source="{Binding Items}"/>
</Page.Resources>

<!--
    This grid acts as a root panel for the page that defines two rows:
    * Row 0 contains the back button and page title
    * Row 1 contains the rest of the page layout
-->
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid.ChildrenTransitions>
        <TransitionCollection>
            <EntranceThemeTransition/>
        </TransitionCollection>
    </Grid.ChildrenTransitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="140"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition x:Name="primaryColumn" Width="420"/>
        <ColumnDefinition x:Name="secondaryColumn" Width="*"/>
    </Grid.ColumnDefinitions>

    <!-- Back button and page title -->
    <Grid x:Name="titlePanel">
        <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 Title}" Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1" 
                    IsHitTestVisible="false" TextWrapping="NoWrap" VerticalAlignment="Bottom" Margin="0,0,0,40"/>
    </Grid>

    <!-- Vertical scrolling item list -->
    <GridView
        x:Name="itemListView"
        AutomationProperties.AutomationId="ItemsListView"
        AutomationProperties.Name="Items"
        TabIndex="1"
        Grid.Row="1"
        Margin="-10,-10,0,0"
        Padding="120,0,0,60"
        ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
        IsSwipeEnabled="False"
        SelectionChanged="ItemListView_SelectionChanged">
        <GridView.ItemTemplate>
            <DataTemplate>
                <Grid Margin="6">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
                    <Border Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}" Width="60" Height="60">
                        <Image Source="{Binding ImagePath}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/>
                    </Border>
                    <StackPanel Grid.Column="1" Margin="10,0,0,0">
                        <TextBlock Text="{Binding Title}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap" MaxHeight="40"/>
                        <TextBlock Text="{Binding Subtitle}" Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap"/>
                    </StackPanel>
                </Grid>
            </DataTemplate>
        </GridView.ItemTemplate>
        <ListView.ItemContainerStyle>
            <Style TargetType="FrameworkElement">
                <Setter Property="Margin" Value="0,0,0,10"/>
            </Style>
        </ListView.ItemContainerStyle>
    </GridView>


    <!-- Details for selected item -->
    <ScrollViewer
        x:Name="itemDetail"
        AutomationProperties.AutomationId="ItemDetailScrollViewer"
        Grid.Column="1"
        Grid.RowSpan="2"
        Padding="60,0,66,0"
        DataContext="{Binding SelectedItem, ElementName=itemListView}"
        HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto"
        ScrollViewer.HorizontalScrollMode="Disabled" ScrollViewer.VerticalScrollMode="Enabled"
        ScrollViewer.ZoomMode="Disabled">

        <Grid x:Name="itemDetailGrid" Margin="0,60,0,50">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>

            <Image Grid.Row="1" Margin="0,0,20,0" Width="180" Height="180" Source="{Binding ImagePath}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/>
            <StackPanel x:Name="itemDetailTitlePanel" Grid.Row="1" Grid.Column="1">
                <TextBlock x:Name="itemTitle" Margin="0,-10,0,0" Text="{Binding Title}" Style="{StaticResource SubheaderTextBlockStyle}"/>
                <TextBlock x:Name="itemSubtitle" Margin="0,0,0,20" Text="{Binding Subtitle}" Style="{StaticResource SubtitleTextBlockStyle}"/>
            </StackPanel>
            <TextBlock Grid.Row="2" Grid.ColumnSpan="2" Margin="0,20,0,0" Text="{Binding Content}" Style="{StaticResource BodyTextBlockStyle}"/>
        </Grid>
    </ScrollViewer>

    <VisualStateManager.VisualStateGroups>

        <!-- Visual states reflect the application's view state -->
        <VisualStateGroup x:Name="ViewStates">
            <VisualState x:Name="PrimaryView" />
            <VisualState x:Name="SinglePane">
                <Storyboard>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="primaryColumn" Storyboard.TargetProperty="Width">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="*"/>
                    </ObjectAnimationUsingKeyFrames>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="secondaryColumn" Storyboard.TargetProperty="Width">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
                    </ObjectAnimationUsingKeyFrames>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetail" Storyboard.TargetProperty="Visibility">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                    </ObjectAnimationUsingKeyFrames>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView" Storyboard.TargetProperty="Padding">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="120,0,90,60"/>
                    </ObjectAnimationUsingKeyFrames>
                </Storyboard>
            </VisualState>
            <!--
                When an item is selected and only one pane is shown the details display requires more extensive changes:
                 * Hide the master list and the column it was in
                 * Move item details down a row to make room for the title
                 * Move the title directly above the details
                 * Adjust padding for details
             -->
            <VisualState x:Name="SinglePane_Detail">
                <Storyboard>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="primaryColumn" Storyboard.TargetProperty="Width">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
                    </ObjectAnimationUsingKeyFrames>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView" Storyboard.TargetProperty="Visibility">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                    </ObjectAnimationUsingKeyFrames>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetail" Storyboard.TargetProperty="(Grid.Row)">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
                    </ObjectAnimationUsingKeyFrames>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetail" Storyboard.TargetProperty="(Grid.RowSpan)">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
                    </ObjectAnimationUsingKeyFrames>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="titlePanel" Storyboard.TargetProperty="(Grid.Column)">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
                    </ObjectAnimationUsingKeyFrames>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetailGrid" Storyboard.TargetProperty="Margin">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="0,0,0,60"/>
                    </ObjectAnimationUsingKeyFrames>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetail" Storyboard.TargetProperty="Padding">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="120,0,90,0"/>
                    </ObjectAnimationUsingKeyFrames>
                </Storyboard>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
</Grid>

它运作良好,但我的问题是GridViewitemDetail在单独的滚动条上,我希望它们在同一个滚动条上,因此详细信息随{{{1}移动1}}。

我的第一个想法是使用Grouped GridView,一个项目组具有不同的项目模板(详细信息模板),尽管这似乎是一个很长的路要解决一个简单的问题。

他们是一个更容易的方式吗?

详细要求:

  • 页面必须符合任意数量的任务&#39; (项目)尽可能(因此) GridView)。

  • Page必须使用所有空间。

  • 页面必须说明他们是1个任务和许多任务。

根据这些要求,我必须确保如果列表中只有一个任务,则任务的详细信息将填充屏幕上的其余空间,以便没有负载空白&# 39 ;.同样,如果有很多任务,我必须尽可能多地将它们放到页面上,这样用户就可以看到它们。

2 个答案:

答案 0 :(得分:1)

使用群组是一种方式,但我认为即使使用DataTemplateSelector,您也可能无法获得不同尺寸的内容。

Hub控件可能是您最好的选择(它在VS中的一个基本应用模板中)。

另一个选择是将GridView和您的详细信息网格放在水平方向的StackPanel内,并将其放在ScrollViewer中。只需确保您的GridView仅显示有限数量的项目。水平滚动浏览所有项目只是为了查看一个项目的详细信息可能不是最好的用户体验。我真的切换到了ListView

答案 1 :(得分:0)

我找到了一个比我认为更简单的解决方案。

如果我用<Grid/>包裹我的基础<ScrollViewer/>(类似于Filip Skakun建议的那样),我可以滚动页面上的所有内容。但是,正如我的评论所述,GridView没有垂直限制。

要解决此问题,我可以将GridView.MaxHeight设置为实例化页面时的窗口高度(减去标题栏),如果窗口大小发生变化则再次设置。

public SplitPage1()
{
    itemListView.MaxHeight = Window.Current.Bounds.Height - 140; // 140 being the height of the titlbar.
    // Start listening for Window size changes 
    // Change the itemListView.MaxHeight when it does.
    Window.Current.SizeChanged += Window_SizeChanged;
}

这是Window_SizeChanged方法。

private void Window_SizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
{
    // Set the MaxHeight of the girdview.
    itemListView.MaxHeight = Window.Current.Bounds.Height - 140;
    this.InvalidateVisualState();
}

这创造了我追求的用户体验。