在 WPF 双向绑定中,如何检查是 UI 元素还是 ViewModel 触发了绑定更改?

Dav*_*cia 7 c# data-binding wpf xaml mvvm

我不确定要搜索什么关键字……迷失在谷歌的海洋中。

我在 ViewModel 中的可视元素(滑块)和数值之间指定了双向数据绑定。我想区分用户发起的值更改和基于 ViewModel 的值更改,以便我可以有选择地触发应用程序中其他位置的事件。如何在 XAML 文件的代码隐藏中执行此操作?

2015 年 2 月 26 日更新:在回复 Amit 的问题时,为什么我需要此功能是因为我实际上有多个可视元素设置为 2 向数据绑定到同一 ViewModel 源,因此不区分会导致无限循环(堆栈溢出)在对依赖代码的回调中,这些代码本身具有更新相同值的能力。

抛开 - 第一次在 SO 上适当地使用“堆栈溢出”时,难道不应该有声望点吗?

Ste*_*nds 2

我认为简短的答案是:并非如此。

当您从 XAML 元素绑定到 ViewModel 属性时,WPF 绑定系统最终将调用 ViewModel 中的属性设置器。一旦进入 setter 方法,您就无法了解如何到达那里。您可以检查堆栈以了解您来自哪里,但这将是非常脆弱的代码,并且可能也很慢。

如果该属性仅由 XAML 绑定或 ViewModel 设置,那么您可以在 ViewModel 中设置某种布尔标志,如下所示:

bool _isBeingSetByVM;

public int Number
{
    get { return _number; }
    set
    {
        if (_isBeingSetByVM)
        {
            // ViewModel has set the property
            // Do whatever you need to do...
            _isBeingSetByVM = false;
        }

        if (_number != value)
        {
            _number = value;
            OnPropertyChanged("Number");  // generate PropertyChanged event
        }
    }
}
int _number;

void SomeMethodInVM()
{
    _isBeingSetByVM = true;
    Number = 42;
}
Run Code Online (Sandbox Code Playgroud)

但同样,这是非常脆弱的代码,很难维护。正如@Amit 在他的评论中所说,更好的问题可能是为什么你需要这样做。