根据您的设计偏好,您可以完全避免事件订阅及其相关的内存泄漏。如果您按照这些思路构建 Video 类...
public class Video : INotifyPropertyChanged
{
public Video(Action summationCallback)
{
_summationCallback = summationCallback;
}
private readonly Action _summationCallback;
private double _duration;
public double Duration
{
get { return _duration; }
set
{
if (value != _duration)
{
_duration = value;
OnPropertyChanged("Duration");
if (_summationCallback != null)
{
_summationCallback();
}
}
}
}
#region INotifyPropertyChanged Implementation
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string name)
{
var handler = System.Threading.Interlocked.CompareExchange(ref PropertyChanged, null, null);
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
#endregion
}
此类在其构造函数中接受一个委托,并在每次“持续时间”属性更改时调用它。要将其连接起来,您可以按照这些思路实现 ViewModel ......
public class MyViewModel : INotifyPropertyChanged
{
public ObservableCollection<Video> MyCollection { get; set; }
public MyViewModel()
{
MyCollection = new ObservableCollection<Video>();
Video v = new Video(SummationCallback);
MyCollection.Add(v);
}
private void SummationCallback()
{
SumOfAllDurations = MyCollection.Sum(q=>q.Duration)
}
private double _sumOfAllDurations;
public double SumOfAllDurations
{
get { return _sumOfAllDurations; }
set
{
if (value != _sumOfAllDurations)
{
_sumOfAllDurations = value;
OnPropertyChanged("SumOfAllDurations");
}
}
}
#region INotifyPropertyChanged Implementation
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string name)
{
var handler = System.Threading.Interlocked.CompareExchange(ref PropertyChanged, null, null);
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
#endregion
}
并将您的标签绑定到“SumOfAllDurations”。此策略将使所有内容保持同步,而无需求助于事件订阅(如果用户删除了视频,这将是孤立的)并使用 WPF 管道来处理绑定。