我正在制作一个Win Store应用程序,并面临处理方向的问题。
有一个网格,我想在方向改变时修改它的设计。 两侧的堆叠面板(在横向视图中)应在纵向视图中转到顶部和底部。
目前,我已经使用所有控件创建了两个网格,并根据方向调整它们,并使用VisualStateManager切换可见性属性。
但我希望用一个网格实现这一目标,任何建议对我都有很大的帮助。
以下图片是该应用的概念设计:
答案 0 :(得分:6)
使用单个网格执行此操作很困难,但可能。
首先,您可能想要做的是减少对方向的担忧,而不是担心水平宽度。这样,如果用户以不会有很多水平空间(类似于纵向模式)的方式快照应用程序,您可以显示类似的体验。
现在,进入网格。
这里的关键是你从一个Grid
移动,实际上是3列,一个是1列。因此,您需要修改单元格的ColumnSpan
属性。
到目前为止您所绘制的内容有3 Columns
,每个Width
GridLength *
。从那里开始。
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
</Grid>
接下来,我们要设置Rows
。最好将行数设置为您需要的最大行数,这是我的计数6.如果您将它们全部设置为Auto
,那么空Rows
(在横向方向)将消失。
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Width="Auto"/>
<RowDefinition Width="Auto"/>
<RowDefinition Width="Auto"/>
<RowDefinition Width="Auto"/>
<RowDefinition Width="Auto"/>
<RowDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
</Grid>
现在,创建一些基本内容。我只想创建一堆不同的StackPanel
并将它们命名为它们。
我将默认Grid/Row
值设置为Landscape
的值。我也在第二行使用了两行&#39; (包含StackPanel
s 1和2)。两个StackPanel
的{{1}}都为2,以便进行补偿。
RowSpan
现在我们为您的<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Width="Auto"/>
<RowDefinition Width="Auto"/>
<RowDefinition Width="Auto"/>
<RowDefinition Width="Auto"/>
<RowDefinition Width="Auto"/>
<RowDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Name="HeaderRow" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3"/>
<StackPanel Name="StackPanel1" Grid.Row="1" Grid.Column="0" Grid.RowSpan="2"/>
<StackPanel Name="Content" Grid.Row="1" Grid.Column="1"/>
<StackPanel Name="BlueSection" Grid.Row="2" Grid.Column="1"/>
<StackPanel Name="StackPanel2" Grid.Row="1" Grid.Column="2" Grid.RowSpan="2"/>
<StackPanel Name="FooterRow" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="3"/>
</Grid>
方向提供了一个很好的定义。它会根据其中的内容自动垂直调整大小,但您可以随意执行任何最小尺寸调整。
既然我们已经完成了这项工作,我们只需要为不同的尺寸创建一些Landscape
。在一个VisualStates
中,我们将准确定义我们已经完成的工作。另一方面,我们将创建一个新的。我正在命名他们&#39; Landscape&#39;和&#39;肖像&#39;现在,但我建议做一些类似于&#39; Mid&#39;和&#39; Wide&#39;,然后根据给定的VisualState
定义使用哪个。为了空间,我省略了以前的定义。
从技术上讲,我们不需要包含Bounds
定义,但我将其作为附加示例包含在内。
注意:在第二张图片中,您有Landscape
StackPanel2
。我在下面反映了这一点。如果您需要更改,只需将Footer
的行定义更改为StackPanel2
,将4
的行定义更改为Footer
。
5
你差不多完成了。您只需要<Grid>
...
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="OrientationStates">
<!-- What we've already defined -->
<VisualState x:Name="Landscape">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.RowSpan)" Storyboard.TargetName="StackPanel1">
<DiscreteObjectKeyFrame KeyTime="0" Value="2"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.ColumnSpan)" Storyboard.TargetName="StackPanel1">
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
</ObjectAnimationUsingKeyFrames>
<!-- Stack Panel 2 -->
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.RowSpan)" Storyboard.TargetName="StackPanel2">
<DiscreteObjectKeyFrame KeyTime="0" Value="2"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.ColumnSpan)" Storyboard.TargetName="StackPanel2">
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Row)" Storyboard.TargetName="StackPanel2">
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Column)" Storyboard.TargetName="StackPanel2">
<DiscreteObjectKeyFrame KeyTime="0" Value="2"/>
</ObjectAnimationUsingKeyFrames>
<!-- Content -->
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Row)" Storyboard.TargetName="Content">
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Column)" Storyboard.TargetName="Content">
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.ColumnSpan)" Storyboard.TargetName="Content">
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
</ObjectAnimationUsingKeyFrames>
<! -- Blue Section -->
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Row)" Storyboard.TargetName="BlueSection">
<DiscreteObjectKeyFrame KeyTime="0" Value="2"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Column)" Storyboard.TargetName="BlueSection">
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.ColumnSpan)" Storyboard.TargetName="BlueSection">
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
</ObjectAnimationUsingKeyFrames>
<!-- Footer -->
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Row)" Storyboard.TargetName="Footer">
<DiscreteObjectKeyFrame KeyTime="0" Value="3"/>
</ObjectAnimationUsingKeyFrames>
</VisualState>
<!-- The New Section -->
<VisualState x:Name="Portrait">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.RowSpan)" Storyboard.TargetName="StackPanel1">
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.ColumnSpan)" Storyboard.TargetName="StackPanel1">
<DiscreteObjectKeyFrame KeyTime="0" Value="3"/>
</ObjectAnimationUsingKeyFrames>
<!-- Stack Panel 2 -->
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.RowSpan)" Storyboard.TargetName="StackPanel2">
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.ColumnSpan)" Storyboard.TargetName="StackPanel2">
<DiscreteObjectKeyFrame KeyTime="0" Value="3"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Row)" Storyboard.TargetName="StackPanel2">
<DiscreteObjectKeyFrame KeyTime="0" Value="5"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Column)" Storyboard.TargetName="StackPanel2">
<DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
</ObjectAnimationUsingKeyFrames>
<!-- Content -->
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Row)" Storyboard.TargetName="Content">
<DiscreteObjectKeyFrame KeyTime="0" Value="2"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Column)" Storyboard.TargetName="Content">
<DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.ColumnSpan)" Storyboard.TargetName="Content">
<DiscreteObjectKeyFrame KeyTime="0" Value="3"/>
</ObjectAnimationUsingKeyFrames>
<! -- Blue Section -->
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Row)" Storyboard.TargetName="BlueSection">
<DiscreteObjectKeyFrame KeyTime="0" Value="3"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Column)" Storyboard.TargetName="BlueSection">
<DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.ColumnSpan)" Storyboard.TargetName="BlueSection">
<DiscreteObjectKeyFrame KeyTime="0" Value="3"/>
</ObjectAnimationUsingKeyFrames>
<!-- Footer -->
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Row)" Storyboard.TargetName="Footer">
<DiscreteObjectKeyFrame KeyTime="0" Value="4"/>
</ObjectAnimationUsingKeyFrames>
</VisualState>
</VisualStateGroup>
<VisualStateManager.VisualStateGroups>
</Grid>
收听Page
并回复即可!它需要引用您的WindowSizeChanged
。因此,我建议添加Grid
或类似于基本x:Name="ContentGrid"
定义的内容。如:
Grid
<Grid x:Name="ContentGrid">
的示例将假设您已完成此操作。
WindowSizeChanged
然后,在private void WindowSizeChanged(object sender, WindowSizeChangedEventArgs windowSizeChangedEventArgs)
{
if (windowSizeChangedEventArgs.Size.Width < 800)
{
VisualStateManager.GoToState(ContentGrid, "Portrait", true);
}
else
{
VisualStateManager.GoToState(ContentGrid, "Landscape", true);
}
}
Page
和OnNavigatedTo
...
OnNavigatedFrom
请务必在从页面导航时删除protected override void OnNavigatedTo(NavigationEventArgs e)
{
Window.Current.SizeChanged += WindowSizeChanged;
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
Window.Current.SizeChanged -= WindowSizeChanged;
}
SizeChanged
处理程序,否则您的应用会无限期地在内存中保留您的页面副本。这是如何创建一个有趣的内存泄漏。
那就是它!在更改大小时,您的主页面将通知您的网格它需要重新配置自己,它将以所述方式执行此操作。显然你不能直接粘贴它,但你应该能够使用它。请务必将event
更改为您指定的控件。
希望这有助于编码!