使用 VisualStateManager 在 Windows 10 应用程序中移动 MainPage.xaml 中的 UserControl

Move a UserControl in MainPage.xaml in Windows 10 application using VisualStateManager

我的页面 (XAML) 中有一个 UserControl,它代表一个工具栏,位于页面顶部,具有三个按钮。由于这是一个 Windows 10 应用程序,我希望当屏幕宽度较宽时,这个顶部工具栏会沿着屏幕的左边缘移动,以便垂直显示工具栏。我尝试使用 VisualStateManager VisualStates,但这只会帮助更改属性而不是元素。我需要将 ColumnDefinitions 更改为 RowDefinitions 以便垂直显示按钮。

我现在唯一的解决方案是创建第二个 UserControl (VerticalToolBar.xaml) 并使用 VSM 隐藏和取消隐藏两者。但我确信对于可能很常见的事情有更简单的解决方案。我想使用一个 UserControl,因为现在我正在复制他们的代码。它们的行为相同。

这是 TopHorizontalToolBar.xaml 的 XAML:

<UserControl
x:Class="Innobec.Mobile.Apps.CityScope.UserControls.TopHorizontalToolBar"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Innobec.Mobile.Apps.CityScope.UserControls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="80"
d:DesignWidth="400">

<Grid x:Name="MainToolbar">
    <Grid Grid.Row="0" Background="Red">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Button x:Name="pinButton" HorizontalAlignment="Center" Grid.Column="0" Background="Red" Click="pinButton_Click" Style="{StaticResource TopHorizontalToolBarButtonStyle}">
            <Image Source="/Assets/Top-Pin-Icon-60px.png" Stretch="None"/>
        </Button>
        <Button x:Name="newsButton" HorizontalAlignment="Center" Grid.Column="1" Background="Red" Click="newsButton_Click" Style="{StaticResource TopHorizontalToolBarButtonStyle}">
            <Image Source="/Assets/Top-News-Icon-60px.png" Stretch="None"/>
        </Button>
        <Button x:Name="weatherButton" HorizontalAlignment="Center" Grid.Column="2" Background="Red" Click="weatherButton_Click" Style="{StaticResource TopHorizontalToolBarButtonStyle}">
            <Image Source="/Assets/Top-Weather-Icon-60px.png" Stretch="None"/>
        </Button>
    </Grid>
</Grid>

我的 VerticalToolBar 除了使用 .在我的 MainPage.xaml 上,我有以下显示我放置这些用户控件的位置:

    <Page 
x:Class="Innobec.Mobile.Apps.CityScope.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Innobec.Mobile.Apps.CityScope"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:maps="using:Windows.UI.Xaml.Controls.Maps"
xmlns:toolbars="using:Innobec.Mobile.Apps.CityScope.UserControls"
mc:Ignorable="d">

<Grid x:Name="MainGrid">
    <Grid.Resources>
        <Storyboard x:Name="SlideInfoUp">
            <DoubleAnimationUsingKeyFrames Storyboard.TargetName="LocationDetails" Storyboard.TargetProperty="Height" EnableDependentAnimation="True">
                <SplineDoubleKeyFrame KeyTime="0:0:0.25" Value="130"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
        <Storyboard x:Name="SlideInfoDown">
            <DoubleAnimationUsingKeyFrames Storyboard.TargetName="LocationDetails" Storyboard.TargetProperty="Height" EnableDependentAnimation="True">
                <SplineDoubleKeyFrame KeyTime="0:0:0.25" Value="0"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </Grid.Resources>
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="WindowStates">
            <VisualState x:Name="WideState">
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="660"/>
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="TopBarGrid.Visibility" Value="Collapsed"/>
                    <Setter Target="LeftBarGrid.(Grid.Column)" Value="0"/>
                    <Setter Target="LeftBarGrid.(Grid.RowSpan)" Value="3"/>
                    <Setter Target="LeftBarGrid.Visibility" Value="Visible"/>
                    <Setter Target="LeftBarGrid.Width" Value="Auto"/>
                    <Setter Target="ContentGrid.(Grid.Row)" Value="1"/>
                    <Setter Target="ContentGrid.(Grid.Column)" Value="1"/>
                </VisualState.Setters>
            </VisualState>
            <VisualState x:Name="NarrowState">
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="1"/>
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="TopBarGrid.(Grid.Row)" Value="0"/>
                    <Setter Target="TopBarGrid.(Grid.ColumnSpan)" Value="2"/>
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="50"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition x:Name="LeftColumn" Width="Auto"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <Grid x:Name="TopBarGrid">
        <toolbars:TopHorizontalToolBar/>
    </Grid>
    <Grid x:Name="LeftBarGrid" Grid.Column="0" Grid.RowSpan="2" Visibility="Collapsed" Width="60">
        <toolbars:VerticalToolBar />
    </Grid>
    <Grid x:Name="ContentGrid" Grid.Row="1" Grid.Column="1" Grid.RowSpan="2" Grid.ColumnSpan="2" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid  Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="Auto"/>                        
            </Grid.RowDefinitions>                    
            <ListView x:Name="itineraryListView" 
                        Grid.Row="1"  
                        Margin="24,24,0,0" 
                        SelectionMode="None">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <RelativePanel Margin="0,24,0,0">
                            <TextBlock x:Name="address" 
                                        Width="100" 
                                        TextWrapping="Wrap" 
                                        Text="{Binding FormattedAddress}"/>
                            <ListView 
                                ItemsSource="{Binding ItineraryInfosAtPoint}" 
                                RelativePanel.RightOf="address" 
                                SelectionMode="None">
                                <ListView.ItemTemplate>
                                    <DataTemplate>
                                        <TextBlock Text="{Binding Title}"/>
                                    </DataTemplate>
                                </ListView.ItemTemplate>
                            </ListView>
                        </RelativePanel>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>                  
        </Grid>
        <Grid>
            <maps:MapControl x:Name="InfoMap"
                             Loaded="InfoMap_Loaded"                              
                             MapElementClick="InfoMap_MapElementClick"  
                             TransitFeaturesVisible="False" 
                             BusinessLandmarksVisible="False" 
                             LandmarksVisible="True" 
                             ZoomLevelChanged="InfoMap_ZoomLevelChanged"                                 
                             MapServiceToken="qB0QfPpDYI6Qh8SWJvS5~x5_U5L-2_-eVF0AE_2qg2w~AuuXeJ_QLZ_6APb7Y3vr3x_opC-CkytS298EJUAjPpPo6pSj1hzYpCIdCTUkH1pf"/>
        </Grid>           
    </Grid>
    <Grid Grid.Row="2" Grid.Column="1"><!--Grid.ColumnSpan="2"-->
        <Viewbox MaxWidth="500" HorizontalAlignment="Left" VerticalAlignment="Center">
            <toolbars:LocationDetails x:Name="LocationDetails" Height="0"/>
        </Viewbox>
    </Grid>
    <Grid Grid.Row="3" Grid.ColumnSpan="2">
        <toolbars:BottomToolBar x:Name="BottomToolBar"/>
    </Grid>
</Grid>

一种选择是使用 StackPanel 代替 Grid 来放置按钮。然后,您可以通过视觉状态改变水平和垂直方向,快速切换面板布局。

还有一个 Windows10 选项是使用全新的 RelativePanel 来固定按钮。此控件允许您定义其中的子项相对于彼此的位置。对于水平布局,每个按钮都可以设置在前一个按钮的右侧,对于垂直布局,每个按钮都可以设置在下方。这些相关属性也可以通过视觉状态进行更改。对于水平视图,上面的控件看起来像这样。

 <RelativePanel >
        <Button x:Name="pinButton" Background="Red" Click="pinButton_Click" Style="{StaticResource TopHorizontalToolBarButtonStyle}">
            <Image Source="/Assets/Top-Pin-Icon-60px.png" Stretch="None"/>
        </Button>
        <Button x:Name="newsButton"  Background="Red" Click="newsButton_Click" Style="{StaticResource TopHorizontalToolBarButtonStyle}"
                RelativePanel.RightOf="pinButton">
            <Image Source="/Assets/Top-News-Icon-60px.png" Stretch="None"/>
        </Button>
        <Button x:Name="weatherButton"  Background="Red" Click="weatherButton_Click" Style="{StaticResource TopHorizontalToolBarButtonStyle}"
                RelativePanel.RightOf="newsButton">
            <Image Source="/Assets/Top-Weather-Icon-60px.png" Stretch="None"/>
        </Button>
 </RelativePanel>

这是一篇很好的博客 post,更深入地介绍了 RelativePanel 并为其设置视觉状态: http://blog.galasoft.ch/posts/2015/04/building-adaptive-layout-in-windows-10-with-relativepanel-and-adaptivetrigger/