如何将MAUI窗口SizeChanged事件关联至页面以适配布局?
解决方案:将MAUI窗口SizeChanged事件关联到页面并实现布局适配
针对你的需求,这里提供几种实用方案,帮你把窗口尺寸变化事件关联到单个页面,实现不同屏幕尺寸下的布局切换:
方案1:利用页面自身的SizeChanged事件(跨平台通用)
MAUI的ContentPage本身自带SizeChanged事件,当窗口尺寸调整时,页面尺寸会同步变化,该事件会自动触发。这是最简单的跨平台方案,无需针对Windows写原生代码:
XAML代码
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="YourApp.MainPage" SizeChanged="OnPageSizeChanged"> <!-- 定义两种布局 --> <Grid x:Name="MainContainer"> <!-- 宽屏网格布局 --> <Grid x:Name="FullGrid" IsVisible="True"> <!-- 网格内容 --> </Grid> <!-- 小屏卡片布局 --> <StackLayout x:Name="CardLayout" IsVisible="False"> <!-- 卡片内容 --> </StackLayout> </Grid> </ContentPage>
后台代码
private void OnPageSizeChanged(object sender, EventArgs e) { // 获取当前页面尺寸(对应窗口尺寸) var currentSize = this.Size; // 根据宽度阈值切换布局 AdjustLayout(currentSize.Width); } private void AdjustLayout(double windowWidth) { const double wideScreenThreshold = 1000; FullGrid.IsVisible = windowWidth > wideScreenThreshold; CardLayout.IsVisible = windowWidth <= wideScreenThreshold; }
方案2:通过消息中心传递尺寸变化(适合MVVM架构)
如果你的项目采用MVVM模式,可使用CommunityToolkit.Mvvm的WeakReferenceMessenger(比旧版MessagingCenter更安全,避免内存泄漏),在应用级事件中发送尺寸消息,页面订阅后更新布局:
1. 定义消息类
using CommunityToolkit.Mvvm.Messaging; using Microsoft.Maui.Graphics; public class WindowResizedMessage : ValueChangedMessage<Size> { public WindowResizedMessage(Size value) : base(value) { } }
2. 修改应用级SizeChanged事件发送消息
#if WINDOWS static void OnSizeChanged(object sender, Microsoft.UI.Xaml.WindowSizeChangedEventArgs args) { var newWindowSize = new Size(args.Size.Width, args.Size.Height); WeakReferenceMessenger.Default.Send(new WindowResizedMessage(newWindowSize)); } #endif
3. 页面订阅消息并调整布局
using CommunityToolkit.Mvvm.Messaging; public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); // 订阅窗口尺寸变化消息 WeakReferenceMessenger.Default.Register<WindowResizedMessage>(this, (_, message) => { var windowSize = message.Value; AdjustLayout(windowSize.Width); }); } private void AdjustLayout(double windowWidth) { const double wideScreenThreshold = 1000; FullGrid.IsVisible = windowWidth > wideScreenThreshold; CardLayout.IsVisible = windowWidth <= wideScreenThreshold; } // 页面销毁时取消订阅,避免内存泄漏 protected override void OnDisappearing() { base.OnDisappearing(); WeakReferenceMessenger.Default.Unregister<WindowResizedMessage>(this); } }
方案3:直接在页面绑定Windows原生窗口事件
如果你需要直接获取Windows原生窗口的尺寸信息,可在页面中直接绑定原生窗口的SizeChanged事件:
#if WINDOWS protected override void OnAppearing() { base.OnAppearing(); // 获取Windows原生窗口实例 var nativeWindow = Microsoft.Maui.Controls.Window.Current.Handler.PlatformView as Microsoft.UI.Xaml.Window; nativeWindow.SizeChanged += OnNativeWindowSizeChanged; } protected override void OnDisappearing() { base.OnDisappearing(); var nativeWindow = Microsoft.Maui.Controls.Window.Current.Handler.PlatformView as Microsoft.UI.Xaml.Window; nativeWindow.SizeChanged -= OnNativeWindowSizeChanged; } private void OnNativeWindowSizeChanged(object sender, Microsoft.UI.Xaml.WindowSizeChangedEventArgs args) { var windowWidth = args.Size.Width; AdjustLayout(windowWidth); } #endif private void AdjustLayout(double windowWidth) { const double wideScreenThreshold = 1000; FullGrid.IsVisible = windowWidth > wideScreenThreshold; CardLayout.IsVisible = windowWidth <= wideScreenThreshold; }
补充提示
- MAUI使用独立设备像素作为尺寸单位,无需额外处理DPI适配,直接用宽度值判断即可
- 可根据实际需求调整宽屏/小屏的阈值(比如平板可设为800)
- 测试时可手动拖拽窗口边缘,验证布局切换是否流畅
内容的提问来源于stack exchange,提问作者MaxTheCoder
相关产品推荐
相关产品推荐

