1

私はWPFアプリケーションを開発しています。データグリッドにバインドされた ObservableCollection があります。この部分ですべてが正常に機能しています。コレクションが更新されると、グリッドが更新されます。グリッドを手動で更新すると、コレクションも更新されます。

これで、Video.Duration プロパティの合計をコレクションに格納するクラス ローカル プロパティができました。これは、Label コントロールにバインドされています。コレクションに新しいエントリを追加すると (ユーザーがファイルをグリッドにドロップしたときに実装されます)、期間の合計が計算され、適切に表示されます。ただし、ユーザーがセルの値を更新すると、このイベントは処理されません。

INOtifyPropertyChanged について読みましたが、必要なようです。しかし、私はその概念を完全には理解していません。

私が考えていることは次のとおりです。 1. ビデオ クラスに INOtifyPropertyChanged を実装します。2. duration プロパティのセッターでプロパティ変更イベントを発生させる

これで、sum プロパティがメイン クラスに追加されました。どのようにして propertychanged イベントをサブスクライブし、ビデオの再生時間が更新されるたびに合計再生時間を再計算できるようにしますか。

4

2 に答える 2

1

設計の好みによっては、イベント サブスクリプションとそれに関連するメモリ リークを完全に回避できます。これらの方針に沿って 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
    }

このクラスは、コンストラクターでデリゲートを受け取り、'Duration' プロパティが変更されるたびにそれを呼び出します。それを接続するには、これらの線に沿って 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 配管を使用してバインディングを処理します。

于 2013-07-13T23:50:32.723 に答える
1

あなたのアプローチは私にはいいですね。がSum プロパティの変更をリッスンする場所であるため、INotifyPropertyChangedメイン クラスにも実装する必要があります。BindingLabel

INotifyPropertyChangedVideo クラスと Main クラスに実装すると、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()
    }
}

覚えておくべきことの 1 つはNotifyPropertyChanged、ビデオが削除されたとき、またはアンロードするときはいつでも、イベントの登録を解除することです。これにより、メモリ リークを防ぐことができます。

Video.NotifyPropertyChanged -= OnVideoPropertyChanged;
于 2013-07-13T23:16:12.243 に答える