首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >缓冲PropertyChanged事件

缓冲PropertyChanged事件
EN

Stack Overflow用户
提问于 2014-12-03 11:51:42
回答 2查看 1.4K关注 0票数 4

我有一个wpf应用程序,它的所有viewModel都是从实现INotifyPropertyChanged的类NotifyPropertyChangeClass继承的(见下文)。

我想节流发送到视图的通知,以避免由于发送的通知太多而出现滞后。到目前为止,我实现的是使用反应扩展的方法样本来延迟每个属性。

问题是Gui被throttlingPeriod更新得很晚。在这段时期开始的时候,第一次举办这样的活动,会让人更有反应:

NotifyPropertyChangeClass的代码:

代码语言:javascript
复制
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));
        }
    }
}

我怎样才能实现我想要的?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-12-03 14:46:46

我没有试过,但你可以试试这个:

代码语言:javascript
复制
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
EN

Stack Overflow用户

发布于 2020-04-04 21:36:01

我还想在同时通知大量更改时(它正在拖住列表视图),我还想节流PropertyChanged通知程序。

最后,我使用了时间检查,因此如果一个新事件是在上次事件之后500 on通过之前引发的,它将在触发对所有属性的更新之前将此事件和任何进一步的事件阻塞500 on。代码如下

代码语言:javascript
复制
private DateTime _lastPropertyChange = DateTime.Now - TimeSpan.FromMinutes(1);
private readonly TimeSpan _propertyChangeBuffer = TimeSpan.FromMilliseconds(500);
private bool _propertyChangeBlock = false;

public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        if (_propertyChangeBlock)
            return;

        if (_lastPropertyChange < DateTime.Now - _propertyChangeBuffer)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            _lastPropertyChange = DateTime.Now;
        }
        else
        {
            _propertyChangeBlock = true;
            ThreadPool.QueueUserWorkItem(p =>
            {
                Thread.Sleep(_propertyChangeBuffer);
                _propertyChangeBlock = false;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(null));
            });
        }
    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27271089

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档