【问题标题】:RaisePropertyChanged does not notify parentRaisePropertyChanged 不通知父母
【发布时间】:2017-07-25 22:05:39
【问题描述】:

我们有一个包含子集合的父类。这两个类都支持使用 Template10 进行更改通知。更改通知适用于每个类(即当我们更新同一类中的属性时),如下所示,但我们无法从子级触发父级更改通知。

public class ParentViewModel : ViewModelBase
{
    public string ParentString { get }
    public decimal? Net { get { return Total / (1 + TaxRate / 100); } }        
    public decimal? Tax { get { return Total - Net; } }
    decimal? _Total = default(decimal?);
    public decimal? Total
    {
        get
        {
            return _Total;
        }
        set
        {
            Set(ref _Total, value);
            RaisePropertyChanged(nameof(Net));
            RaisePropertyChanged(nameof(Tax));
        }
    }

    public ObservableCollection<ChildViewModel> MyChildren { get; set; }

我们发现我们可以在ParentViewModel 中使用RaisePropertyChanged 来开火

Net { get { return Total / (1 + TaxRate / 100); } }

和

Tax { get { return Total - Net; } }

在ChildViewModel 我们有ChildString。我们希望将 ChildString 的更改通知 ParentString。

public class ChildViewModel : ViewModelBase
{
    ParentViewModel MyParent { get; set; }
    string _ChildString = default(string);
    public string ChildString
    {
        get
        {
            return _ChildString;
        }
        set
        {
            Set(ref _ChildString, value);
            RaisePropertyChanged(nameof(this.MyParent.ParentString));
        }
    }

但是ParentString 没有更新。当ChildString 更新时,我们如何强制ParentString 更新?

【问题讨论】:

  • this.MyParent 分配在哪里?也许this so question 有帮助
  • @Lei Yang MyParent 由创建 ChildViewModel 实例的任何方法分配。谢谢你的链接。接受的答案对我们有用。

标签: c# mvvm uwp template10


【解决方案1】:

不管nameof 参数如何,当您调用ChildViewModel.RaisePropertyChanged 时,您会在子视图模型上触发事件。

nameof 操作员无法“更改”事件源。您需要一种以某种方式解雇父母PropertyChanged 的方法。最简单的方法是在ParentViewModel中制作适当的方法:

public void RaiseParentStringChanged()
{
    RaisePropertyChanged(nameof(ParentString));
}

并从孩子那里调用它:

public string ChildString
{
    get
    {
        return _ChildString;
    }
    set
    {
        Set(ref _ChildString, value);

        // assuming, that parent is assigned at this point
        MyParent.RaiseParentStringChanged();
    }
}

但是如果 ParentString 的改变是带来这种依赖的唯一原因,那么从孩子中抛弃父母会很好。

由于MyChildren 是一个可观察的集合,您可以订阅它的CollectionChanged 事件。添加新子时,您可以订阅其PropertyChanged,并注意ChildString 的更改以引发适当的父事件。

是这样的:

// non-related code is omitted
public class ParentViewModel: ViewModelBase
{
    private ObservableCollection<ChildViewModel> children;

    public string ParentString { get; }

    // don't do collection properties on view models
    // as get-set ones, unless you know exactly what are you doing;
    // usually you don't need to set them explicitly from outside
    public ObservableCollection<ChildViewModel> MyChildren
    {
        get
        {
            if (children == null)
            {
                children = new ObservableCollection<ChildViewModel>();
                children.CollectionChanged += ChildrenChanged;
            }
            return children;
        }
    }

    private void ChildrenChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        // assuming, that only two actions ("add" and "remove") are available;
        // if you really need to nadle "reset" and "replace", add appropriate code;
        // note, that "reset" doesn't provide acceess to removed items
        switch (e.Action)
        {
            case NotifyCollectionChangedAction.Add:
                ((ChildViewModel)e.NewItems[0]).PropertyChanged += ChildPropertyChanged;
                break;
            case NotifyCollectionChangedAction.Remove:
                ((ChildViewModel)e.OldItems[0]).PropertyChanged -= ChildPropertyChanged;
                break;
        }
    }

    private void ChildPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == nameof(ChildViewModel.ChildString))
        {
            RaisePropertyChanged(nameof(ParentString));
        }
    }
}

【讨论】:

  • 谢谢@Dennis。你能举个例子说明如何订阅对 children 集合的更改吗?
猜你喜欢
  • 2020-08-25
  • 1970-01-01
  • 2017-03-31
  • 1970-01-01
  • 1970-01-01
  • 2017-03-25
  • 2019-12-27
  • 2019-05-21
相关资源
最近更新 更多