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

跨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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 08:35:59