Buffered PropertyChanged Events

I have a wpf application with all viewModel inheritance from the NotifyPropertyChangeClass implementing INotifyPropertyChanged (see below).

I want to turn off notifications sent for review to avoid lagging due to too many notifications sent. So far I have achieved a delay for each property using the Reactive Extension Sample method.

The problem is that Gui is updated late with throttling. It would be better to react to the first event raised at the beginning of the period as follows:

More graphic explanation

NotifyPropertyChangeClass code:

using System;
using System.ComponentModel;
using System.Reactive.Linq;

namespace MyNameSpace
{
    public class NotifyPropertyChangeClass : INotifyPropertyChanged
    {
        public NotifyPropertyChangeClass(int throttlingPeriod)
        {
            var obs = Observable.FromEventPattern<PropertyChangedEventHandler, PropertyChangedEventArgs>(
               h => this.privatePropertyChanged += h, h => this.privatePropertyChanged -= h);
            var groupedByName = obs.Select(o => o.EventArgs.PropertyName).GroupBy(x => x).SelectMany(o => o.Sample(TimeSpan.FromMilliseconds(throttlingPeriod)));
            groupedByName.Subscribe(o =>
            {
                PropertyChangedEventHandler handler = PropertyChanged;
                if (handler != null)
                    handler(this, new PropertyChangedEventArgs(o));
            });
        }
        public event PropertyChangedEventHandler PropertyChanged;
        private event PropertyChangedEventHandler privatePropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = privatePropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

      

How can I achieve what I want?

+3


source to share


1 answer


I haven't tried it, but you can try this:



using System;
using System.ComponentModel;
using System.Reactive.Linq;

namespace MyNameSpace
{
    public class NotifyPropertyChangeClass : INotifyPropertyChanged
    {
        private bool _isThrottling = false;

        public NotifyPropertyChangeClass(int throttlingPeriod)
        {
            var obs = Observable.FromEventPattern<PropertyChangedEventHandler, PropertyChangedEventArgs>(
               h => this.privatePropertyChanged += h, h => this.privatePropertyChanged -= h);
            var groupedByName = obs.Select(o => o.EventArgs.PropertyName).GroupBy(x => x).SelectMany(o => o.Sample(TimeSpan.FromMilliseconds(throttlingPeriod)));
            groupedByName.Subscribe(o =>
            {
                PropertyChangedEventHandler handler = PropertyChanged;
                if (handler != null)
                    handler(this, new PropertyChangedEventArgs(o));
                _isThrottling = false;
            });
        }
        public event PropertyChangedEventHandler PropertyChanged;
        private event PropertyChangedEventHandler privatePropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            // Will fire the first time, the event is raised
            if (!_isThrottling)
            {
                PropertyChangedEventHandler handler = PropertyChanged;
                if (handler != null)
                    handler(this, new PropertyChangedEventArgs(o));
            }

            // Setting to true here will suppress raising the public event 
            // for every subsequent call, until the event is raised
            // by the observable pattern and the flag is set to false again.
            _isThrottling = true;

            // Will always be raised
            PropertyChangedEventHandler handler = privatePropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

      

+1


source







All Articles