WinUI/WindowsAppSdk中页面内容完整切换的最优实现方案
WinUI3/Windows App SDK 页面内容切换(全屏播放)的正确实现方案
针对媒体中心这类场景,要实现选中影片后让MediaPlayerElement占满整个页面,有两种符合官方规范的核心方案,结合你的代码给出具体实现:
一、官方推荐方案:使用VisualStateManager管理布局状态
WinUI3官方推荐通过**视觉状态(VisualState)**来管理同一页面内的不同布局模式,这种方式能保证UI切换的流畅性和可维护性,完全适配你的场景。
具体实现步骤
修改XAML布局,添加视觉状态组
在根Grid中嵌入VisualStateManager.VisualStateGroups,定义「正常布局」和「全屏播放」两种状态:- 正常状态:保持原有布局,显示所有控件
- 全屏播放状态:隐藏标题、描述、影片列表,让
MediaPlayerElement占满整个页面
修改后的完整XAML代码:
<?xml version="1.0" encoding="utf-8" ?> <Page x:Class="WinUI3Demo.Pages.MediaCenterPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="using:WinUI3Demo.Pages" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:models="using:WinUI3Demo.ViewModels" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" mc:Ignorable="d"> <Page.DataContext> <models:MediaModel x:Name="Model" /> </Page.DataContext> <Grid x:Name="RootGrid" Padding="16"> <!-- 添加视觉状态组 --> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="LayoutStates"> <!-- 正常布局状态 --> <VisualState x:Name="NormalLayout"> <VisualState.Setters> <Setter Target="RootGrid.Padding" Value="16"/> <Setter Target="HeaderTextBlock.Visibility" Value="Visible"/> <Setter Target="ContentTextBlock.Visibility" Value="Visible"/> <Setter Target="MediaScrollView.Visibility" Value="Visible"/> <Setter Target="PlayerViewbox.Stretch" Value="UniformToFill"/> </VisualState.Setters> </VisualState> <!-- 全屏播放状态 --> <VisualState x:Name="FullScreenPlayer"> <VisualState.Setters> <Setter Target="RootGrid.Padding" Value="0"/> <Setter Target="HeaderTextBlock.Visibility" Value="Collapsed"/> <Setter Target="ContentTextBlock.Visibility" Value="Collapsed"/> <Setter Target="MediaScrollView.Visibility" Value="Collapsed"/> <!-- 让播放器Viewbox占满整个根Grid --> <Setter Target="PlayerGrid.Row" Value="0"/> <Setter Target="PlayerGrid.RowSpan" Value="2"/> <Setter Target="PlayerViewbox.Stretch" Value="Fill"/> </VisualState.Setters> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <!-- 给播放器所在Grid命名,方便状态控制 --> <Grid x:Name="PlayerGrid" Grid.Row="0"> <Grid.RowDefinitions> <RowDefinition Height="10*" /> <RowDefinition Height="1*" /> <RowDefinition Height="1*" /> </Grid.RowDefinitions> <Viewbox Grid.Row="1" HorizontalAlignment="Left"> <TextBlock x:Name="HeaderTextBlock" FontWeight="ExtraBold" /> </Viewbox> <Viewbox x:Name="PlayerViewbox" Grid.Row="0" Margin="0,15,0,0" HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="UniformToFill"> <MediaPlayerElement x:Name="MediaPlayer" AreTransportControlsEnabled="False" AutoPlay="True" DoubleTapped="MediaPlayer_DoubleTapped"/> </Viewbox> <Viewbox Grid.Row="2" HorizontalAlignment="Left"> <TextBlock x:Name="ContentTextBlock" Width="880" TextWrapping="WrapWholeWords" /> </Viewbox> </Grid> <!-- 给滚动视图命名 --> <ScrollView x:Name="MediaScrollView" Grid.Row="1" Height="250" Padding="0,10,0,0" ContentOrientation="Horizontal"> <ItemsView x:Name="MediaCenterItemView" ItemsSource="{x:Bind Model.Objects, Mode=OneWay}" SelectionChanged="ItemsView_SelectionChanged"> <ItemsView.Layout> <LinedFlowLayout ItemsStretch="Fill" LineHeight="250" MinItemSpacing="15" /> </ItemsView.Layout> <ItemsView.ItemTemplate> <DataTemplate x:DataType="models:MediaObject"> <ItemContainer> <Grid> <Image Source="{x:Bind Thumbnail, Mode=OneWay}" Stretch="Uniform" /> </Grid> </ItemContainer> </DataTemplate> </ItemsView.ItemTemplate> </ItemsView> </ScrollView> </Grid> </Page>后台代码切换视觉状态
在SelectionChanged事件中切换到全屏播放状态,同时添加退出全屏的逻辑:private void ItemsView_SelectionChanged(object sender, SelectionChangedEventArgs e) { // 选中影片后切换到全屏播放状态 VisualStateManager.GoToState(this, "FullScreenPlayer", true); // 加载并播放选中影片 var selectedMedia = MediaCenterItemView.SelectedItem as MediaObject; if (selectedMedia != null) { MediaPlayer.Source = MediaSource.CreateFromUri(new Uri(selectedMedia.MediaUrl)); HeaderTextBlock.Text = selectedMedia.Title; ContentTextBlock.Text = selectedMedia.Description; } } // 双击播放器退出全屏 private void MediaPlayer_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e) { VisualStateManager.GoToState(this, "NormalLayout", true); }
二、备选方案:利用MediaPlayerElement内置全屏功能
如果你不需要自定义全屏后的页面布局,仅需要播放器自身全屏,可以开启AreTransportControlsEnabled="True",此时控件会自带全屏切换按钮,点击后自动进入系统级全屏,无需额外布局修改。但这种方式无法隐藏页面其他元素,适合仅需要播放器全屏的场景。
关于官方实现指南
WinUI3官方文档中,针对页面布局切换推荐使用VisualStateManager,针对媒体播放的全屏场景,既支持控件内置的全屏功能,也支持结合视觉状态的自定义布局,这两种方案均符合官方设计规范。
内容的提问来源于stack exchange,提问作者miniHessel
相关产品推荐
相关产品推荐

