如何在类内的类中的属性上使用INotifyPropertyChanged.

本文关键字:INotifyPropertyChanged 属性 | 更新日期: 2023-09-27 17:57:46

我的问题似乎是"范围",尽管我不确定这是正确的术语。当设置了自定义对象中的属性时,我想通知只读列表重新评估其自身。我相信它根本没有意识到它的存在。也许有一种简单的方法可以解决这个问题,我想不出,但我还是一片空白。

我发现这很难用语言表达,所以下面是我对预期发生的事情的评论的简化代码。

数据绑定到的对象内的属性:

private CvarAspectRatios _aspectRatio = new CvarAspectRatios("none", GetRatio());
public CvarAspectRatios AspectRatio
{
    get { return _aspectRatio; }
    set
    {                                                 // This setter never gets hit since I bind to this 
        if (value != null)                            // object's 'Value' property now.
        {
            _aspectRatio = value;
            NotifyPropertyChanged("AspectRatio");
            NotifyPropertyChanged("ResolutionList");  // I want to inform ResolutionList
        }                                             // that it needs to repopulate based
    }                                                 // on this property: AspectRatio
}
private ResolutionCollection _resolutionList = ResolutionCollection.GetResolutionCollection();
public ResolutionCollection ResolutionList
{
   get 
   {
       ResolutionCollection list = new ResolutionCollection();
       if (AspectRatio != null && AspectRatio.Value != null)
       {
           foreach (Resolutions res in _resolutionList.Where(i => i.Compatibility == AspectRatio.Value.Compatibility))
           {
               list.Add(res);
           }
           return list;
       }
       return _resolutionList;
   }
}

CvarAspectRatios类:

public class CVarAspectRatios : INotifyPropertyChanged
{
    private string _defaultValue;
    public string DefaultValue
    {
        get { return _defaultValue; }
        set { _defaultValue = value; NotifyPropertyChanged("DefaultValue"); }
    }
    private AspectRatios _value;
    public AspectRatios Value
    {
        get { return _value; }
        set 
        { 
            _value = value; 
            NotifyPropertyChanged("Value"); 
            NotifyPropertyChanged("ResolutionList");  // This value gets set, and I'd like for ResolutionList to update
        }                                             // but it cannot find ResolutionList. No errors or anything. Just
    }                                                 // no update.
    public AspectRatios() { }
    public AspectRatios(string defaultValue, AspectRatios val)
    {
        DefaultValue = defaultValue;
        Value = val;
    }
    // Implementation of INotifyPropertyChanged snipped out here
}

你们怎么想?如果你想要一个示例应用程序,我可以制作一个。

如何在类内的类中的属性上使用INotifyPropertyChanged.

由于CVarAspectRatios实现了INotifyPropertyChanged,因此可以让视图模型类订阅AspectRatio的PropertyChanged事件。

public class YourViewModel 
{
    public YourViewModel()
    {
        AspectRatio.PropertyChanged += AspectRatio_PropertyChanged;
    }
    void AspectRatio_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "Value")
            NotifyPropertyChanged("ResolutionList");
    }        
}

请记住,如果您放弃了那个AspectRatio对象(如果对象引用发生了更改,而不仅仅是该对象的value属性),那么您应该取消订阅被丢弃对象上的事件。

将现有代码转换为应该工作的代码:

private CvarAspectRatios _aspectRatio; //No field initialization because that would not attach event handler, you could do it though and take care of the handler alone in the ctor
public CvarAspectRatios AspectRatio
{
    get { return _aspectRatio; }
    set
    {
        if (_aspectRatio != value) // WTH @ "value != null"
        {
            _aspectRatio.PropertyChanged -= AspectRatio_PropertyChanged;
            _aspectRatio = value;
            _aspectRatio.PropertyChanged += new PropertyChangedEventHandler(AspectRatio_PropertyChanged);
            NotifyPropertyChanged("AspectRatio");
        }
    }
}
void AspectRatio_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == "Value")
    {
        NotifyPropertyChanged("ResolutionList");
    }
}

为什么不考虑将ResolutionList重新填充到一个单独的私有方法中,该方法从AspectRatios的setter调用?

如果列表需要根据更改的属性进行更新,则列表(或列表管理器对象,为了更好地封装)通常需要订阅托管该属性的对象的PropertyChanged事件。如果列表本身是同一对象的属性(如本例所示),那么属性的setter调用更新列表的方法会更简单、更精简。