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

.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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 22:23:12