【发布时间】:2019-01-26 23:24:58
【问题描述】:
我有一个类层次结构。相关位包括在下面。我期待当通过 WPF 绑定更改 FilterCritetionInteger.CriterionValue 时,我会在我的 FilterCriterionCollection 中收到通知。但是,在调用 FilterCriterionInteger.CriterionValue 设置器时,永远不会调用 FilterCriterionCollection.Criterion_PropertyChanged 方法。
显然我误解了某些东西,或者连接不正确。我只是没有找到它。为什么我的通知没有发生? (如果需要更多上下文,请告诉我。)
ViewModelBase
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler pcHandler = this.PropertyChanged;
if (pcHandler != null)
{
PropertyChangedEventArgs args = new PropertyChangedEventArgs(propertyName);
pcHandler(this, args);
}
}
}
FilterCriterionBase
public abstract class FilterCriterionBase : ViewModelBase
{
public abstract bool IsValid { get; }
}
FilterCriterionInteger
public class FilterCriterionInteger : FilterCriterionBase
{
private string _criterionValue = "0";
public string CriterionValue
{
get { return _criterionValue; }
set
{
_criterionValue = value;
OnPropertyChanged("IsValid");
}
}
public int? MaxValue { get; private set; } = null;
public override bool IsValid
{
get
{
if (int.TryParse(_criterionValue, out int i))
{
if (MaxValue.HasValue && (i > MaxValue)) return false;
}
else
{
return false;
}
return true;
}
}
}
FilterCriterionCollection
public class FilterCriteriaCollection : ViewModelBase
{
public FilterCriteriaCollection()
{
Criteria.CollectionChanged += Criteria_CollectionChanged;
}
~FilterCriteriaCollection()
{
Criteria.CollectionChanged -= Criteria_CollectionChanged;
}
public ObservableCollection<FilterCriterionBase> Criteria { get; private set; } = new ObservableCollection<FilterCriterionBase>();
private void Criteria_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
foreach (FilterCriterionBase fb in e.NewItems)
{
fb.PropertyChanged += Criterion_PropertyChanged;
}
break;
case NotifyCollectionChangedAction.Remove:
foreach (FilterCriterionBase fb in e.NewItems)
{
fb.PropertyChanged -= Criterion_PropertyChanged;
}
break;
}
}
private bool _isValid;
public bool IsValid
{
get { return _isValid; }
private set { _isValid = value; OnPropertyChanged("IsValid"); }
}
private void Criterion_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
using (FilterCriterionBase criterion = sender as FilterCriterionBase)
{
switch (e.PropertyName)
{
case "IsValid":
{
bool isvalid = true;
foreach(FilterCriterionBase fcb in Criteria)
{
isvalid = fcb.IsValid;
if (!isvalid) break;
}
IsValid = isvalid;
break;
}
}
}
}
}
【问题讨论】:
-
字符串显示“isValid”但在 CriterionValue 属性中
-
@Charlie - 这是一个触发“IsValid”属性重新评估的调用。带有大写“I”的“IsValid”是属性的公共名称。我看不出有什么问题。你能说得更具体点吗?
-
也尝试添加:OnPropertyChanged("CriterionValue")。重新评估没问题,但如果你绑定 CriterionValue,那么 CriterionValue 必须有一个 changedevent。
-
更改来自 WPF 绑定。在我的场景中,更改永远不会在内部发生,因此没有人需要通知。一旦用户更改了值,我只需要重新评估有效性。
-
@DigitalCamel 附带说明:为什么你有
using声明?你打算在你的事件处理程序中处理事件发送者吗?这看起来不对。