首页 > 解决方案 > OnPropertyChanged 2 级更新

问题描述

搜索没有给我带来任何线索,我有点不知所措。到目前为止,WPF 是自学的,所以我可能会忽略一些简单的东西。

<Window.DataContext>
    <local:MainViewModel/>
</Window.DataContext>

<TextBlock Text={Binding BoundTextProperty}"/>

这是简化的xml

public class MainViewModel
{
    private Model Data;
    public MainViewModel()
    {...}
    public string BoundTextProperty => Data.BoundTextProperty;
    ...
}

绑定的属性引用了模型中保存数据的属性

public class Model : INotifyPropertyChanged
{
    private long number;
    public long Number
    {
        get { return number; }
        set 
        {
            number = value;
            OnPropertyChanged(nameof(BoundTextProperty));
        }
    }

    public string BoundTextProperty => $"Some text {Number} some text again";

    public virtual event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

我发誓它在某些时候有效。该字符串还有几个其他变量,但这是它如何工作的基础,或者说不是。

我的问题是绑定是否真的可以冒泡,如果可以,为什么不呢?

标签: c#wpfbindinginotifypropertychanged

解决方案


您需要为PropertyChanged您在 XAML 中绑定到的源属性引发事件。在这种情况下,您绑定到BoundTextPropertyof,MainViewModel这意味着MainViewModel该类应该引发PropertyChanged事件。

源属性是否包装了确实引发PropertyChanged事件的类的另一个属性并不重要。通知视图的是绑定的源对象。

您也可以直接绑定到“模型”属性,前提是您Data在视图模型中变成公共属性:

public Model Data { get; private set; }
...
<TextBlock Text="{Binding Data.BoundTextProperty}"/>

如果您选择坚持使用包装器属性,则MainViewModel必须在模型更新时实现INotifyPropertyChanged事件并引发事件:PropertyChanged

public class MainViewModel : INotifyPropertyChanged
{
    private readonly Model Data;

    public MainViewModel()
    {
        Data = new Model();
        Data.PropertyChanged += Data_PropertyChanged;
    }

    private void Data_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        OnPropertyChanged("BoundTextProperty");
    }

    public string BoundTextProperty => Data.BoundTextProperty;

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

推荐阅读