OnPropertyChanged 2级更新

时间:2018-07-05 12:40:57

标签: c# wpf binding inotifypropertychanged

搜索并没有给我任何线索,我有点茫然。 到目前为止,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));
    }
}

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

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

2 个答案:

答案 0 :(得分:1)

您必须添加用于将Model的PropertyChanged事件从ViewModel冒泡到View的代码。 这是一个示例(基于您的代码):

public class MainViewModel : ViewModelBase
{
    private readonly Model Data;

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

    private void ModelOnPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        switch (e.PropertyName)
        {
            case nameof(Model.BoundTextProperty):
                OnPropertyChanged(nameof(MainViewModel.BoundTextProperty));
                break;
            // add cases for other properties here:
        }
    }

    public string BoundTextProperty => Data.BoundTextProperty;
}

public class Model : ModelBase
{
    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 abstract class ViewModelBase : Base
{
    // add other ViewModel related stuff here
}


public abstract class ModelBase : Base
{
    // add other Model related stuff here
}

public abstract class Base : INotifyPropertyChanged
{
    public virtual event PropertyChangedEventHandler PropertyChanged;

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

答案 1 :(得分:1)

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

source属性是否包装确实引发PropertyChanged事件的类的另一个属性都没有关系。通知视图的是绑定的源对象。

如果您将PropertyChanged转换为视图模型中的公共属性,则也可以直接绑定到“ model”属性:

Data

如果您选择坚持使用wrapper属性,则无论何时更新模型,public Model Data { get; private set; } ... <TextBlock Text="{Binding Data.BoundTextProperty}"/> 必须实现MainViewModel事件并引发INotifyPropertyChanged事件:

PropertyChanged