.NET Maui中Shell Flyout Item的IsVisible属性数据绑定不更新问题排查求助
解决.NET MAUI Shell Flyout菜单项可见性绑定不更新的问题
兄弟,我一眼就看穿问题所在了——你不小心创建了两个完全独立的ShowParametersViewModel实例!
仔细看你的代码:
AppShell.xaml里你new了一个ShowParametersViewModel作为Shell的绑定上下文DisplayPage.xaml里又new了另一个ShowParametersViewModel作为页面的绑定上下文
这就导致:你点击按钮修改的是DisplayPage那个ViewModel的ShowParameters属性,而AppShell绑定的是另一个完全无关的ViewModel实例,属性值根本没变化,Flyout的可见性当然不会更新啦!初始值能生效只是因为AppShell自己的ViewModel初始值起作用而已。
解决方案:确保全局只用同一个ViewModel实例
这里给你两种简单可行的方法,适合新手快速解决:
方法1:用单例模式(最直接)
修改你的ShowParametersViewModel.cs,改成单例模式,确保整个应用只有一个实例:
using System; using System.ComponentModel; using System.Windows.Command; namespace TSDZ2Monitor { public class ShowParametersViewModel : INotifyPropertyChanged { // 全局唯一实例 private static ShowParametersViewModel _instance; public static ShowParametersViewModel Instance => _instance ??= new ShowParametersViewModel(); // 私有构造函数,禁止外部直接new private ShowParametersViewModel() {} public event PropertyChangedEventHandler PropertyChanged; bool showParameters = true; public bool ShowParameters { get { return showParameters; } set { if (value == showParameters) return; showParameters = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ShowParameters))); // 顺便建议用nameof代替硬编码字符串,避免拼写错误 } } public ICommand ShowParametersCommand => new Command(ChangeShowParameters); public void ChangeShowParameters() { Console.WriteLine($"Before {ShowParameters}"); ShowParameters = !ShowParameters; Console.WriteLine($"After {ShowParameters}"); } } }
然后修改两个页面的绑定上下文,都指向这个单例:
- 修改
AppShell.xaml的Shell.BindingContext:
<Shell.BindingContext> <x:Static Member="local:ShowParametersViewModel.Instance"/> </Shell.BindingContext>
- 修改
DisplayPage.xaml的ContentPage.BindingContext:
<ContentPage.BindingContext> <x:Static Member="local:ShowParametersViewModel.Instance"/> </ContentPage.BindingContext>
方法2:用依赖注入(更优雅,推荐后续项目使用)
.NET MAUI默认支持依赖注入,你可以在MauiProgram.cs里把ViewModel注册为单例:
builder.Services.AddSingleton<ShowParametersViewModel>();
然后在AppShell和DisplayPage的构造函数里注入这个ViewModel:
// AppShell.cs public AppShell(ShowParametersViewModel viewModel) { InitializeComponent(); BindingContext = viewModel; } // DisplayPage.cs public DisplayPage(ShowParametersViewModel viewModel) { InitializeComponent(); BindingContext = viewModel; }
这样框架会自动给两个页面注入同一个ViewModel实例,避免手动管理单例的麻烦,更符合MVVM的最佳实践。
验证效果
改完之后,再点击"Show parameters"按钮,你会发现Flyout里的Bluetooth项会跟着ShowParameters属性的变化显示/隐藏了——因为现在两个绑定上下文用的是同一个ViewModel,PropertyChanged事件能正确通知到AppShell的绑定啦!
内容的提问来源于stack exchange,提问作者gfmoore
相关产品推荐
相关产品推荐

