我的班级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
属性实际上已经改变了?
答案 0 :(得分:0)
已编辑:没有注意到这是一个吸气剂,而不是一个二传手。重点仍然是一样的。简单地实现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));
}
答案 1 :(得分:0)
ViewModel不会在此处触发任何PropertyChanged,因为ViewModel的属性未更改。已更改的实际属性FooProp
是Foo类的属性,而不是ViewModel。
为了根据IsButtonEnabled
功能启用/禁用按钮,您必须跟踪MyList的所有元素,并查看是否进行了任何更改。因此,以下内容应该有效:
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&lt;&gt;之后到ObservableCollection&lt;&gt;能够自动跟踪/处理列表中的项目。