繁体   English   中英

当BindingList元素的属性更改时,缺少PropertyChanged事件

[英]Missing PropertyChanged event when BindingList elements has properties changed

我有一个类ViewModel具有属性MyList类型BindingList<Foo>

ViewModel实现INotifyPropertyChanged

Foo具有属性FooProp

Foo实现INotifyPropertyChanged

ViewModel具有此属性:

public bool IsButtonEnabled
  {
    get
    {
      return MyList.Any(x=> x.FooProp!=null);
   }
}

我有一个带有按钮的视图。 按钮的Enabled属性绑定到IsButtonEnabled

但是,当一个元素的按钮没有得到启用MyList有它的FooProp集。 我注意到ViewModel不会在此处触发PropertyChanged事件。 为什么不? 我应该如何去使视图模型注意到它的IsButtonEnabled属性实际上已经改变了?

编辑:没有注意到这是一个吸气剂,而不是一个二传手。 观点还是一样。 仅仅实现INotifyPropertyChanged接口并不会自动添加您需要的所有内容。 您需要创建触发事件的方法(如下)。 然后,您需要在所有属性的SETTER中调用该方法。

您不应该自己触发PropertyChanged事件吗?

public bool IsButtonEnabled
{
    get
    {
        return MyList.Any(x=> x.FooProp!=null);

        // assuming you named the method this
        OnPropertyChanged("IsButtonEnabled");
    }
}

INotifyPropertyChanged接口仅为您创建事件。 您需要自己从ViewModel触发事件。

如果尚未创建该方法,则该方法通常可以使用。 当ViewModel的属性更改时,将显式调用此方法。

private void OnPropertyChanged(string propertyName)
{
    var handler = PropertyChanged;
    if (handler != null)
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

由于未更改ViewModel的属性,因此ViewModel不会在此处触发任何PropertyChanged。 更改的实际属性FooProp是类Foo的属性,而不是ViewModel的属性。

为了基于IsButtonEnabled功能启用/禁用按钮,您将必须跟踪IsButtonEnabled所有元素,并查看是否进行了任何更改。 因此,以下应工作:

public class Foo : INotifyPropertyChanged
{
    void OnPropertyChanged(string propertyName) { /* ... */ }
    public object FooProp 
    { 
        get { return _obj; }
        set 
        {
            _obj = value;
            OnPropertyChanged("FooProp");
        }
    }
}

public class ViewModel : INotifyPropertyChanged
{
    void OnPropertyChanged(string propertyName) { /* ... */ }

    private List<Foo> _myList;
    public List<Foo> MyList 
    { 
        get { return _myList; }
        set 
        {
            _myList = value;
            foreach(var item in _myList) 
            {
                HandleItem(item);
            }
        }
    }

    void AddItem(Foo item) 
    {
        MyList.Add(item);
        HandleItem(item);
    }
    void HandleItem(Foo item) 
    {
        item.PropertyChanged += (s, e) =>
        {
            if(e.PropertyName == "FooProp")
        };
    }
    void ItemPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if(e.PropertyName == "FooProp") OnPropertyChanged("IsButtonEnabled");
    }
    public bool IsButtonEnabled
    {
        get
        {
          return MyList.Any(x=> x.FooProp!=null);
        }
    }
}

请注意,在这种情况下,您需要使用ViewModel.AddItem()才能将项目添加到MyList中(可以使用MyList.Add(),但此时不会触发正确的通知)。

同样,上面的代码也不是最好的方法-只是说明您的案例应如何工作。 了解了之后,您可能将把List <>替换为ObservableCollection <>,以便能够自动跟踪/处理列表中的项目。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM