You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WinUI/WindowsAppSdk中页面内容完整切换的最优实现方案

WinUI3/Windows App SDK 页面内容切换(全屏播放)的正确实现方案

针对媒体中心这类场景,要实现选中影片后让MediaPlayerElement占满整个页面,有两种符合官方规范的核心方案,结合你的代码给出具体实现:

一、官方推荐方案:使用VisualStateManager管理布局状态

WinUI3官方推荐通过**视觉状态(VisualState)**来管理同一页面内的不同布局模式,这种方式能保证UI切换的流畅性和可维护性,完全适配你的场景。

具体实现步骤

  1. 修改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>
    
  2. 后台代码切换视觉状态
    在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 01:52:11