双窗格视图是一种布局控件,可帮助你管理具有 2 个不同内容区域的应用的显示,例如列表/详细信息视图。
这是正确的控制吗?
当你具有两个不同的但相关的内容区域时,请使用双窗格视图,并:
- 内容应自动重新排列和调整大小,以最适合窗口。
- 内容次要区域应根据可用空间显示/隐藏。
如果需要显示两个内容区域,但不需要双窗格视图提供的大小调整和重新排列,请考虑改用 拆分视图 。
对于导航选项,请使用 导航视图。
工作原理
双窗格视图有两个窗格,可在其中放置内容。 它根据窗口可用的空间调整窗格的大小和排列方式。 可能的窗格布局由 TwoPaneViewMode 枚举定义:
| 枚举值 | Description |
|---|---|
SinglePane |
仅显示一个窗格,由 PanePriority 属性指定。 |
Wide |
根据WideModeConfiguration属性的指定,窗格可以并排显示,也可以显示单个窗格。 |
Tall |
窗格按上下显示,或显示单个窗格,这由TallModeConfiguration属性指定。 |
应用处于宽模式。
处于高模式的应用。
可以通过设置 PanePriority 来配置双窗格视图,以指定在只有一个窗格的空间时显示哪个窗格。 然后,您需要指定 Pane1 在高窗口中显示在顶部或底部,或在宽窗口中显示在左侧或右侧。
双窗格视图处理窗格的大小和排列方式,但仍需要使窗格中的内容适应大小和方向的变化。 有关创建自适应 UI 的详细信息,请参阅响应式布局和 XAML及布局面板。
创建双窗格视图
- 重要 API:TwoPaneView 类
此 XAML 演示如何创建基本 TwoPaneView。
<TwoPaneView>
<TwoPaneView.Pane1>
<Grid Background="{ThemeResource LayerFillColorDefaultBrush}">
<TextBlock Text="Pane 1" Margin="24"
Style="{ThemeResource HeaderTextBlockStyle}"/>
</Grid>
</TwoPaneView.Pane1>
<TwoPaneView.Pane2>
<Grid Background="{ThemeResource LayerFillColorAltBrush}">
<TextBlock Text="Pane 2" Margin="24"
Style="{ThemeResource HeaderTextBlockStyle}"/>
</Grid>
</TwoPaneView.Pane2>
</TwoPaneView>
TwoPaneView 不必是页面布局的根元素。 事实上,通常会在 NavigationView 控件内使用它,该控件为应用提供整体导航。 无论 TwoPaneView 在 XAML 树中的哪个位置,都会适当地调整。
将内容添加到窗格
两个窗格视图的每个窗格都可以包含一个 XAML UIElement。 若要添加内容,通常在每个窗格中放置 XAML 布局面板,然后将其他控件和内容添加到面板。 窗格可以更改大小,并在宽和高模式之间切换,因此你需要确保每个窗格中的内容可以适应这些更改。 有关创建自适应 UI 的详细信息,请参阅响应式布局和 XAML以及布局面板。
此示例创建前面显示的简单图片/信息应用 UI。 内容可以显示在两个窗格中,也可以组合成一个窗格,具体取决于可用空间。 (当只有一个窗格的空间时,可以将 Pane2 的内容移动到 Pane1 中,让用户滚动以查看任何隐藏的内容。稍后将在“ 响应模式更改 ”部分中看到此代码。
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" MinHeight="40"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<CommandBar DefaultLabelPosition="Right">
<AppBarButton x:Name="Share" Icon="Share" Label="Share" Click="Share_Click"/>
<AppBarButton x:Name="Print" Icon="Print" Label="Print" Click="Print_Click"/>
</CommandBar>
<TwoPaneView
x:Name="MyTwoPaneView"
Grid.Row="1"
MinWideModeWidth="959"
MinTallModeHeight="863"
ModeChanged="TwoPaneView_ModeChanged">
<TwoPaneView.Pane1>
<Grid x:Name="Pane1Root">
<ScrollViewer>
<StackPanel x:Name="Pane1StackPanel">
<Image Source="Assets\LandscapeImage8.jpg"
VerticalAlignment="Top" HorizontalAlignment="Center"
Margin="16,0"/>
</StackPanel>
</ScrollViewer>
</Grid>
</TwoPaneView.Pane1>
<TwoPaneView.Pane2
<Grid x:Name="Pane2Root">
<ScrollViewer x:Name="DetailsContent">
<StackPanel Padding="16">
<TextBlock Text="Mountain.jpg" MaxLines="1"
Style="{ThemeResource HeaderTextBlockStyle}"/>
<TextBlock Text="Date Taken:"
Style="{ThemeResource SubheaderTextBlockStyle}"
Margin="0,24,0,0"/>
<TextBlock Text="8/29/2019 9:55am"
Style="{ThemeResource SubtitleTextBlockStyle}"/>
<TextBlock Text="Dimensions:"
Style="{ThemeResource SubheaderTextBlockStyle}"
Margin="0,24,0,0"/>
<TextBlock Text="800x536"
Style="{ThemeResource SubtitleTextBlockStyle}"/>
<TextBlock Text="Resolution:"
Style="{ThemeResource SubheaderTextBlockStyle}"
Margin="0,24,0,0"/>
<TextBlock Text="96 dpi"
Style="{ThemeResource SubtitleTextBlockStyle}"/>
<TextBlock Text="Description:"
Style="{ThemeResource SubheaderTextBlockStyle}"
Margin="0,24,0,0"/>
<TextBlock Text="Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna."
Style="{ThemeResource SubtitleTextBlockStyle}"
TextWrapping="Wrap"/>
</StackPanel>
</ScrollViewer>
</Grid>
</TwoPaneView.Pane2>
</TwoPaneView>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="TwoPaneViewStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="Wide">
<VisualState.Setters>
<Setter Target="MyTwoPaneView.Pane1Length"
Value="2*"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
指定要显示的窗格
当双窗格视图只能显示单个窗格时,它使用 PanePriority 属性来确定要显示的窗格。 默认情况下,PanePriority 设置为 Pane1。 下面介绍如何在 XAML 或代码中设置此属性。
<TwoPaneView x:Name="MyTwoPaneView" PanePriority="Pane2">
MyTwoPaneView.PanePriority = TwoPaneViewPriority.Pane2;
窗格大小调整
窗格的大小由 Pane1Length 和 Pane2Length 属性确定。 这些 GridLength 值支持使用自动和星号(*) 调整大小。 有关自动大小和星型大小的说明,请参阅 响应式布局的 XAML 的 布局属性 部分。
默认情况下,Pane1Length设置为Auto并调整其大小以适应其内容。
Pane2Length 设置为 *,并且使用所有剩余空间。
具有默认大小调整的窗格
默认值对于典型的列表/详细信息布局非常有用,其中 Pane1 包含项目列表,而 Pane2 包含很多详细信息。 但是,根据内容,你可能更喜欢以不同的方式划分空间。 在这里,Pane1Length 被设置为 2*,这样它将获得比 Pane2 多一倍的空间。
<TwoPaneView x:Name="MyTwoPaneView" Pane1Length="2*">
双窗格视图,窗格 1 使用屏幕的三分之二,窗格 2 使用屏幕的三分之一。
窗格大小为 2* 和 *
如果将窗格设置为使用自动大小调整,可以通过设置包含窗格内容的高度和宽度 Panel 来控制大小。 在这种情况下,可能需要处理 ModeChanged 事件,并设置内容的高度和宽度约束,以适合当前模式。
以宽或高模式显示
在单个屏幕上,双窗格视图的显示 模式 由 MinWideModeWidth 和 MinTallModeHeight 属性决定。 这两个属性的默认值为 641px,与 NavigationView.CompactThresholdWidth 相同。
下表显示了TwoPaneView中的Height和Width如何确定使用哪种显示模式。
| TwoPaneView 条件 | 模式 |
|---|---|
Width > MinWideModeWidth |
使用Wide模式 |
Width
<= MinWideModeWidth和 Height>MinTallModeHeight |
Tall 模式被使用 |
Width
<= MinWideModeWidth和 Height<= MinTallModeHeight |
使用SinglePane模式 |
丰富的配置选项
MinWideModeWidth 控制双窗格视图进入宽模式的时机。 当可用空间大于Wide属性时,双窗格视图进入MinWideModeWidth模式。 默认值为 641px,但你可以将其更改为所需的任何值。 通常,应将此属性设置为希望窗格的最小宽度。
当双窗格视图处于宽模式时, WideModeConfiguration 属性将确定要显示的内容:
| 枚举值 | Description |
|---|---|
SinglePane |
由PanePriority确定的单个窗格。 窗格占据TwoPaneView的全尺寸(即,在两个方向上都是星型大小)。 |
LeftRight |
Pane1 在左侧/Pane2 在右侧。 两个窗格都按比例垂直调整大小,Pane1的宽度为自动调整,Pane2的宽度为按比例调整。 |
RightLeft |
Pane1 右侧/Pane2 左侧。 这两个窗格在垂直方向上使用星号尺寸调整, Pane2的宽度是自动调整的,Pane1的宽度是使用星号尺寸的。 |
默认设置为 LeftRight。
| 左右 | RightLeft |
|---|---|
|
|
注释
当设备使用从右到左(RTL)语言时,双窗格视图会自动交换顺序:RightLeft 呈现为 LeftRight,LeftRight 呈现为 RightLeft。
高配置选项
当可用空间比MinWideModeWidth更窄且比MinTallModeHeight更高时,双窗格视图将进入Tall模式。 默认值为 641px,但你可以将其更改为所需的任何值。 通常,应将此属性设置为希望窗格的最低高度。
当双窗格视图处于高模式时, TallModeConfiguration 属性将确定要显示的内容:
| 枚举值 | Description |
|---|---|
SinglePane |
由PanePriority确定的单个窗格。 窗格占用了 TwoPaneView 的全部空间(即,它在两个方向上都是星形尺寸)。 |
TopBottom |
Pane1 位于顶部/Pane2 位于底部。 这两个窗格在水平上按比例分配,Pane1 的高度是自动调整的,Pane2 的高度按比例分配。 |
BottomTop |
Pane1 底部/Pane2 顶部。 这两个窗格的宽度为星型大小,Pane2的高度是自动调整的,Pane1的高度为星型大小。 |
默认值为 TopBottom。
| TopBottom | 底部顶部 |
|---|---|
|
|
MinWideModeWidth 和 MinTallModeHeight 的特殊值
可以使用该 MinWideModeWidth 属性阻止双窗格视图进入 Wide 模式 - 只需设置为 MinWideModeWidthDouble.PositiveInfinity 即可。
如果设置为 MinTallModeHeightDouble.PositiveInfinity,它将阻止双窗格视图进入 Tall 模式。
如果设置为 MinTallModeHeight 0,它将阻止双窗格视图进入 SinglePane 模式。
响应模式更改
可以使用只读 Mode 属性获取当前显示模式。 每当双窗格视图更改正在显示的一个或多个窗格时,ModeChanged 事件会在呈现更新内容之前发生。 可以处理事件以响应显示模式下的更改。
重要
最初加载页面时不会发生该 ModeChanged 事件,因此默认 XAML 应表示 UI,因为它应在首次加载时显示。
使用此事件的一种方法是更新应用的 UI,以便用户可以在 SinglePane 模式下查看所有内容。 例如,示例应用具有主窗格(图像)和信息窗格。
纵向模式
当只有足够空间显示一个窗格时,你可以将内容 Pane2 移动到其中 Pane1 ,以便用户可以滚动以查看所有内容。 它的外观如下所示。
SinglePane 模式
请记住,MinWideModeWidth 和 MinTallModeHeight 属性会确定显示模式何时更改,因此您可以通过调整这些属性的值来改变内容在窗格之间移动的时间。
下面是ModeChanged事件处理程序代码,它在Pane1和Pane2之间移动内容。 它还设置一个 VisualState 以在模式下限制图像 Wide 的宽度。
private void TwoPaneView_ModeChanged(TwoPaneView sender, object args)
{
// Remove details content from it's parent panel.
((Panel)DetailsContent.Parent).Children.Remove(DetailsContent);
// Set Normal visual state.
VisualStateManager.GoToState(this, "Normal", true);
// Single pane
if (sender.Mode == TwoPaneViewMode.SinglePane)
{
// Add the details content to Pane1.
Pane1StackPanel.Children.Add(DetailsContent);
}
// Dual pane.
else
{
// Put details content in Pane2.
Pane2Root.Children.Add(DetailsContent);
// If also in Wide mode, set Wide visual state
// to constrain the width of the image to 2*.
if (sender.Mode == TwoPaneViewMode.Wide)
{
VisualStateManager.GoToState(this, "Wide", true);
}
}
}
UWP 和 WinUI 2
重要
本文中的信息和示例是针对使用 Windows App SDK 和 WinUI 3 的应用优化的,但通常适用于使用 WinUI 2 的 UWP 应用。 有关特定于平台的信息和示例,请参阅 UWP API 参考。
本部分包含在 UWP 或 WinUI 2 应用中使用该控件所需的信息。
适用于 UWP 应用的 TwoPaneView 需要 WinUI 2。 有关详细信息,包括安装说明,请参阅 WinUI 2。 此控件的 API 存在于 Microsoft.UI.Xaml.Controls 命名空间中。
- WinUI 2 Apis:TwoPaneView 类
要将本文中的代码与 WinUI 2 配合使用,请使用 XAML 中的别名(我们使用 muxc)来表示项目中包含的 Windows UI 库 API。 有关详细信息,请参阅 WinUI 2 入门 。
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
<muxc:TwoPaneView />