Windows商店应用程序- XAML - GridView和详细信息在一个滚动条



我有一个使用模板的标准拆分页面,尽管我使用的是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是在单独的滚动条上,我希望它们在同一个滚动条上,所以细节与GridView一起移动。

我的第一个想法是使用分组GridView,一个项目组有一个不同的项目模板(细节模板),虽然这似乎是一个很长的路要走,以解决一个简单的问题。

这是一种更简单的方法吗?

详细需求:

  • 页面必须适合尽可能多的"任务"(项目)在它上(因此GridView)。

  • Page必须考虑到它们是一个任务还是多个任务

基于这些要求,我必须确保如果列表中只有一个任务,则任务的详细信息填充屏幕上的其余空间,以便没有加载"空白"。同样,如果有很多任务,我必须尽可能多地把它们放在页面上,这样用户才能看到它们。

使用组是一种方法,但我认为即使使用DataTemplateSelector,您也可能无法获得不同大小的项目。

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

另一种选择是将GridView和你的细节网格都放在水平方向的StackPanel中,并将其放在ScrollViewer中。只要确保你的GridView只显示有限数量的项目。横向滚动查看所有项目的细节可能不是最好的用户体验。我还是用ListView

我找到了一个比我认为需要的简单得多的解决方案。

如果我用<ScrollViewer/>(类似于Filip Skakun建议的)包装我的基础<Grid/>,我可以滚动页面上的所有内容。然而,正如我的评论所说,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();
}

最新更新