跨ViewModel访问属性:如何在ViewModel B中获取ViewModel A的PropertyA
问题场景
现有两个实现INotifyPropertyChanged接口的ViewModel:
- ViewModel A绑定到某视图,代码如下:
class A : INotifyPropertyChanged { public A(){} private bool _propertya; public bool PropertyA { get{return _propertya;} set{_propertya=value; onPropertyChanged("PropertyA");} } private void onPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } public event PropertyChangedEventHandler PropertyChanged; }
- ViewModel B绑定到另一视图,代码如下:
class B : INotifyPropertyChanged { public B(){} private bool _propertyb; public bool PropertyB { get{ return _propertyb;} set{_propertyb=value; onPropertyChanged("PropertyB");} } private void onPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } public event PropertyChangedEventHandler PropertyChanged; }
需求:当PropertyB发生变更时,获取ViewModel A的PropertyA值并根据条件返回布尔值,如何在ViewModel B中获取ViewModel A的实例以访问PropertyA?
可行解决方案
1. 构造函数注入(推荐)
创建ViewModel B实例时,把已初始化的ViewModel A实例通过构造函数传入,让B直接持有A的引用:
修改ViewModel B的代码:
class B : INotifyPropertyChanged { private readonly A _viewModelA; // 构造函数注入ViewModel A实例 public B(A viewModelA) { _viewModelA = viewModelA; } private bool _propertyb; public bool PropertyB { get{ return _propertyb;} set { _propertyb=value; onPropertyChanged("PropertyB"); // 此时可直接访问ViewModel A的PropertyA bool result = _viewModelA.PropertyA && value; // 示例条件判断 } } private void onPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } public event PropertyChangedEventHandler PropertyChanged; }
创建实例时传入A:
var viewModelA = new A(); var viewModelB = new B(viewModelA);
这种方式符合依赖注入原则,代码解耦,易于测试和维护。
2. 共享服务类
如果两个ViewModel需要共享数据,可创建全局共享服务,让A和B都引用该服务,A更新服务数据,B从服务获取:
先定义共享服务:
public class SharedDataService : INotifyPropertyChanged { private bool _propertyA; public bool PropertyA { get => _propertyA; set { _propertyA = value; OnPropertyChanged(nameof(PropertyA)); } } private void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } public event PropertyChangedEventHandler PropertyChanged; }
修改ViewModel A和B:
// ViewModel A class A : INotifyPropertyChanged { private readonly SharedDataService _sharedService; public A(SharedDataService sharedService) { _sharedService = sharedService; } private bool _propertya; public bool PropertyA { get{return _propertya;} set { _propertya=value; onPropertyChanged("PropertyA"); // 更新共享服务中的值 _sharedService.PropertyA = value; } } // 其余代码不变 } // ViewModel B class B : INotifyPropertyChanged { private readonly SharedDataService _sharedService; public B(SharedDataService sharedService) { _sharedService = sharedService; } private bool _propertyb; public bool PropertyB { get{ return _propertyb;} set { _propertyb=value; onPropertyChanged("PropertyB"); // 从共享服务获取PropertyA的值 bool result = _sharedService.PropertyA && value; } } // 其余代码不变 }
使用时创建共享服务实例并传入两个ViewModel:
var sharedService = new SharedDataService(); var viewModelA = new A(sharedService); var viewModelB = new B(sharedService);
这种方式适合多ViewModel共享数据的场景,避免直接引用导致的耦合。
3. 通过视图层级获取(仅适用于WPF等XAML框架)
如果两个视图存在父子关系或在同一窗口中,可通过视图的DataContext获取对方ViewModel实例。比如在WPF中:
在ViewModel B所在视图的代码后台获取主窗口的DataContext:
var mainWindow = Application.Current.MainWindow; var viewModelA = mainWindow.DataContext as A; // 将viewModelA传递给ViewModel B viewModelB.SetViewModelA(viewModelA);
在ViewModel B中添加接收实例的方法:
class B : INotifyPropertyChanged { private A _viewModelA; public void SetViewModelA(A viewModelA) { _viewModelA = viewModelA; } // 其余代码不变,在PropertyB的setter中使用_viewModelA }
这种方式依赖视图层级,耦合度较高,仅适合简单场景。
4. 静态实例(不推荐)
将ViewModel A设为静态实例,但会导致代码耦合严重,难以测试和维护,仅适合极简场景:
// ViewModel A添加静态实例 class A : INotifyPropertyChanged { public static A Instance { get; private set; } public A() { Instance = this; } // 其余代码不变 }
在ViewModel B中直接访问:
class B : INotifyPropertyChanged { private bool _propertyb; public bool PropertyB { get{ return _propertyb;} set { _propertyb=value; onPropertyChanged("PropertyB"); // 直接访问静态实例 bool result = A.Instance.PropertyA && value; } } // 其余代码不变 }
内容的提问来源于stack exchange,提问作者srinivas
相关产品推荐
相关产品推荐

