Question

I have a standard split page using the the template, though I'm using the GridView instead of 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>

It works well enough, though my issue is that the GridView and the itemDetail are on separate scroll bars and i want them to be on the the same one so the details move with the GridView.

My first thought is to use Grouped GridView, with a one item group that has a different item template (the details template), though this seems like a long way round to solve a simple problem.

Is their an easier way?

Detailed Requirements:

  • Page must fit as many 'Tasks' (items) on it as possible (hence GridView).

  • Page must make use of all space.

  • Page must account for their being 1 task and many tasks.

Based on these requirements, I must ensure that if there is only one task in the list, that details of the task fills the rest of the space on the screen so that there is not a load 'white space'. Similarly, if there are lots of tasks, I must fit as many of them onto the page as possible, so the user can see them.

Était-ce utile?

La solution 2

I have found a solution that is a lot simpler then I thought is required.

If i wrap my base <Grid/> with a <ScrollViewer/> (similar to what Filip Skakun suggested) I can scroll everything on the page. However, as my comment states, the GridView then has no vertical bound.

To fix this problem I can set the GridView.MaxHeight to what the window height (minus title bar) when my page is instantiated and again if the window size changes.

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;
}

Here is the Window_SizeChanged method.

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();
}

This creates the UX I was after.

Autres conseils

Using groups is one way, but I think you might not be able to get different size items even with a DataTemplateSelector.

The Hub control might be your best bet (it's in one of the basic app templates in VS).

Another choice is to put both the GridView and your details grid inside of horizontally oriented StackPanel and put that in a ScrollViewer. Just make sure your GridView only shows a limited number of items. Horizontal scrolling through all items just to look at the details of one might not be the best UX. I'd really switch to a ListView for that.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top