Xamarin.Forms跨cs文件更新Xalm中Label可见性问题求助
问题描述
开发涉及以下5个文件:
- MainPageViewModel
- MainPage.cs
- MainPage.Xaml
- MyWordPage.Xaml
- MyWordPage.Xaml.cs
预期实现效果:点击MyWordPage.Xaml.cs中的按钮时,更新MainPage.Xaml内指定Label控件的可见性。
现有代码如下:
MainPageViewModel 代码
bool myfirstmenuvisible = true; public Command<bool> PrimaryMenuVisibleCommand { get; } public MainPageViewModel() { PrimaryMenuVisibleCommand = new Command<bool>(OnprimaryMenuVisible); } public void OnprimaryMenuVisible(bool MyBoolValue) { MyFirstMenuVisible = MyBoolValue; } public bool MyFirstMenuVisible { get => myfirstmenuvisible; set { myfirstmenuvisible = value; OnPropertyChanged(); } }
MyWordPage.Xaml.cs 按钮点击代码
void OnMyButtonClicked(System.Object sender, System.EventArgs e) { Device.BeginInvokeOnMainThread(() => { MainPageVM.PrimaryMenuVisibleCommand.Execute(false); }); }
MainPage.Xaml 代码
<?xml version="1.0" encoding="utf-8" ?> <ContentPage > <ContentPage.BindingContext> <viewmodels:MainPageViewModel/> </ContentPage.BindingContext> <Label Text="you can see " IsVisible="{Binding MyFirstMenuVisible}"></Label> </ContentPage>
问题原因
代码不生效的核心是 ViewModel实例不共享:MainPage在XAML中通过<viewmodels:MainPageViewModel/>单独创建了一个ViewModel实例,MyWordPage中持有的MainPageVM是另一个独立的同类型实例,对后者的属性修改不会同步到MainPage绑定的实例上,自然不会触发UI更新。
解决方案
推荐使用单例ViewModel的方式修复,改动最小,完全适配你现有逻辑:
- 改造MainPageViewModel,添加全局单例入口,将构造函数改为私有避免外部重复创建实例,补全INotifyPropertyChanged的必要实现:
public class MainPageViewModel : INotifyPropertyChanged { // 全局唯一静态实例 public static MainPageViewModel Instance { get; } = new MainPageViewModel(); private bool myfirstmenuvisible = true; public Command<bool> PrimaryMenuVisibleCommand { get; } // 私有构造函数,禁止外部直接new private MainPageViewModel() { PrimaryMenuVisibleCommand = new Command<bool>(OnprimaryMenuVisible); } private void OnprimaryMenuVisible(bool MyBoolValue) { MyFirstMenuVisible = MyBoolValue; } public bool MyFirstMenuVisible { get => myfirstmenuvisible; set { myfirstmenuvisible = value; OnPropertyChanged(); } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
- 修改MainPage.xaml的BindingContext赋值,绑定到全局单例,不要单独创建新实例:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:viewmodels="clr-namespace:你的ViewModel实际命名空间"> <ContentPage.BindingContext> <x:Static Member="viewmodels:MainPageViewModel.Instance"/> </ContentPage.BindingContext> <Label Text="you can see " IsVisible="{Binding MyFirstMenuVisible}"/> </ContentPage>
- 修改MyWordPage.xaml.cs的按钮点击逻辑,直接调用单例实例的命令:
void OnMyButtonClicked(System.Object sender, System.EventArgs e) { Device.BeginInvokeOnMainThread(() => { MainPageViewModel.Instance.PrimaryMenuVisibleCommand.Execute(false); }); }
如果不想用单例,也可以用MVVM工具包的弱引用消息Messenger做跨页面通信,MyWordPage点击时发消息,MainPageViewModel订阅消息后更新属性即可,实现方式更解耦。
内容的提问来源于stack exchange,提问作者hk77
相关产品推荐
相关产品推荐

