Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将类属性绑定到集合的和_C#_Wpf_Events_Delegates_Inotifypropertychanged - Fatal编程技术网

C# 将类属性绑定到集合的和

C# 将类属性绑定到集合的和,c#,wpf,events,delegates,inotifypropertychanged,C#,Wpf,Events,Delegates,Inotifypropertychanged,我正在开发一个WPF应用程序。我有一个绑定到datagrid的ObservableCollection。这部分一切正常。如果集合已更新,则网格将刷新。如果手动更新网格,则集合也会更新 现在,我有一个类本地属性,它存储集合中Video.Duration属性的总和。这是绑定到标签控件的。当我向集合添加一个新条目时(当用户将文件放到网格上时实现),将计算并正确显示持续时间之和。但是,当用户更新单元格中的值时,不会处理此事件 我读过关于INOtifyPropertyChanged的文章,这似乎是我需要的

我正在开发一个WPF应用程序。我有一个绑定到datagrid的ObservableCollection。这部分一切正常。如果集合已更新,则网格将刷新。如果手动更新网格,则集合也会更新

现在,我有一个类本地属性,它存储集合中Video.Duration属性的总和。这是绑定到标签控件的。当我向集合添加一个新条目时(当用户将文件放到网格上时实现),将计算并正确显示持续时间之和。但是,当用户更新单元格中的值时,不会处理此事件

我读过关于INOtifyPropertyChanged的文章,这似乎是我需要的。然而,我并不完全理解这个概念

以下是我的想法: 1.在我的视频类中实现INOtifyPropertyChanged。 2.在duration属性的setter中引发属性更改事件


现在,sum属性在主类中,如何订阅propertychanged事件,以便在更新视频的某个持续时间时重新计算总持续时间。

您的方法听起来不错。您还必须在主类中实现
INotifyPropertyChanged
,因为
标签的
绑定将侦听Sum属性的更改

一旦在视频和主类中实现了
INotifyPropertyChanged
,就会有一个
NotifyPropertyChanged
事件。您可以以与任何活动相同的方式订阅此活动:

private void Subscribe()
{
    foreach(var video in _videos)
    {
        video.NotifyPropertyChanged += OnVideoPropertyChanged;
    }
}

private void OnVideoPropertyChanged(object sender, NotifyPropertyChangedEventArgs e)
{
    if(e.PropertyName == "Duration")
    {
        this.RecalculateSum();
        this.RaisePropertyChanged("Sum");  //Or call this from inside RecalculateSum()
    }
}
要记住的一件事是,每当删除视频或卸载视频时,您都希望取消订阅
NotifyPropertyChanged
事件。这将有助于防止内存泄漏:

Video.NotifyPropertyChanged -= OnVideoPropertyChanged;

根据您的设计偏好,您可以完全避免事件订阅及其关联的内存泄漏。如果你按照这些思路构建视频课程

  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
    }
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
}
此类在其构造函数中接受一个委托,并在每次“Duration”属性更改时调用该委托。要将其连接起来,可以沿以下直线实现ViewModel

  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
    }
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
}
公共类MyViewModel:INotifyPropertyChanged
{
公共ObservableCollection MyCollection{get;set;}
公共MyViewModel()
{
MyCollection=新的ObservableCollection();
视频v=新视频(总和回调);
MyCollection.Add(v);
}
私有void SummationCallback()
{
SumOfAllDurations=MyCollection.Sum(q=>q.Duration)
}
私人双保险期;
公共双保险期
{
获取{return\u sumOfAllDurations;}
设置
{
如果(值!=\u总持续时间)
{
_sumOfAllDurations=值;
房地产变更(“SumOfAllDurations”);
}
}
}
#区域INotifyPropertyChanged实现
公共事件属性更改事件处理程序属性更改;
受保护的虚拟void OnPropertyChanged(字符串名称)
{
var handler=System.Threading.Interlocked.compareeexchange(ref-PropertyChanged,null,null);
if(处理程序!=null)
{
处理程序(此,新PropertyChangedEventArgs(名称));
}
}
#端区
}

并将标签绑定到“SumOfAllDurations”。此策略将使所有内容保持同步,而无需求助于事件订阅(如果用户删除视频,将导致孤立事件),并使用WPF管道处理绑定

谢谢!我采用了这个解决方案,这样我就不必担心订阅/取消订阅活动。但是,我没有创建模型类,而是为total duration实现了DependencyProperty,这样每当total duration的值更新时,标签都会更新。对我来说,通过总结回调是你回答中最重要的方面。