如何让OnPropertyChanged在用户切换设备方向时触发?
设备方向变化时未触发更新的解决方案
你的核心问题是仅在ViewModel构造函数中获取了一次设备方向,没有订阅方向变化的监听事件,所以用户切换设备方向时,Orientation属性不会自动更新。
解决步骤
- 订阅
DeviceDisplay.Current.MainDisplayInfoChanged事件,监听设备显示信息(包括方向)的变化 - 在事件回调中重新计算并更新
Orientation属性 - 实现
IDisposable接口,在ViewModel销毁时取消事件订阅,避免内存泄漏
修改后的TabletPodcastViewModel.cs代码
namespace NerdNewsNavigator2.ViewModel.Tablet; public partial class TabletPodcastViewModel : ObservableObject, IDisposable { #region Properties readonly TwitService _twitService; [ObservableProperty] int _orientation; public ObservableCollection<Podcast> Podcasts { get; set; } = new(); #endregion public TabletPodcastViewModel(TwitService twit) { _twitService = twit; _ = GetPodcasts(); // 初始化方向值 Orientation = OnDeviceOrientationChange(); System.Diagnostics.Debug.WriteLine("Device orientation is: " + Orientation); // 订阅方向变化事件 DeviceDisplay.Current.MainDisplayInfoChanged += OnDisplayInfoChanged; } #region Get the Podcast and set the Podcast List async Task GetPodcasts() { var podcastList = await TwitService.GetListOfPodcasts(); foreach (var item in podcastList) { var temp = await Task.FromResult(FeedService.GetFeed(item)); Podcasts.Add(temp); } } #endregion public int OnDeviceOrientationChange() { return DeviceDisplay.Current.MainDisplayInfo.Orientation == DisplayOrientation.Portrait ? 2 : 3; } // 设备显示信息变化的回调方法 private void OnDisplayInfoChanged(object sender, DisplayInfoChangedEventArgs e) { Orientation = OnDeviceOrientationChange(); System.Diagnostics.Debug.WriteLine("Device orientation updated to: " + Orientation); } [RelayCommand] async Task Tap(string url) { var encodedUrl = HttpUtility.UrlEncode(url); await Shell.Current.GoToAsync($"{nameof(TabletShowPage)}?Url={encodedUrl}"); } // 实现IDisposable,取消事件订阅 public void Dispose() { DeviceDisplay.Current.MainDisplayInfoChanged -= OnDisplayInfoChanged; GC.SuppressFinalize(this); } }
关键说明
- 事件订阅:通过
MainDisplayInfoChanged事件,设备方向变化时会自动触发OnDisplayInfoChanged方法,此时重新计算并赋值Orientation,由于使用了[ObservableProperty],属性变更会自动通知UI更新(无需手动调用OnPropertyChanged)。 - 内存泄漏防护:ViewModel实现
IDisposable后,在页面销毁时(比如MAUI中页面出栈时),需要调用Dispose方法取消事件订阅,防止ViewModel被事件引用无法回收。你可以在TabletPodcastPage的OnDisappearing方法中补充:
protected override void OnDisappearing() { base.OnDisappearing(); if (BindingContext is IDisposable disposable) { disposable.Dispose(); } }
- 初始值优化:构造函数中直接赋值
Orientation = ...即可,[ObservableProperty]会自动触发属性变更通知,不需要额外调用OnPropertyChanged(nameof(Orientation))。
内容的提问来源于stack exchange,提问作者James Crutchley
相关产品推荐
相关产品推荐

