2014-12-03 3 views
3

У меня есть приложение wpf со всем наложением видаModel с классом NotifyPropertyChangeClass, реализующим INotifyPropertyChanged (см. Ниже).Buffer PropertyChanged Events

Я хочу дросселировать уведомления, отправленные на просмотр, чтобы избежать отставания из-за слишком большого количества отправленных уведомлений. До сих пор я достигаю задержки для каждого свойства с использованием метода Образец реактивного расширения.

Проблема в том, что Gui обновляется поздно с помощью дросселирования. Он будет чувствовать себя более отзывчивым иметь первое событие, которое вызывается при запуске периода, как это:

More graphic explanation

Кодекса NotifyPropertyChangeClass:

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)); 
     } 
    } 
} 

Как я могу добиться того, что я хочу?

+0

Я склонен думать, что нет никакого решения, которое удовлетворит ваш запрос точно. Очевидно, что существует некоторое отставание, которое происходит между уведомлениями о событиях, получаемыми в вашем представлении. Вы точно знаете, где и почему происходит это отставание? Но даже если вы знаете причину этого отставания, не уверен, что вы можете это решить. Вероятно, вам придется компенсировать это, уменьшив период действия дросселя или что-то в этом роде. –

ответ

1

Я не пробовал, но вы можете попробовать это:

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)); 
     } 
    } 
} 
+0

Да, это работа! Обратите внимание, что одного bool '_isThrottling' недостаточно, это должен быть словарь с ключом для PropertyName. Спасибо! – Thomas

+0

@Thomas - версия Rx, которую я сделал, должна избегать того, чтобы управлять этим состоянием. –

+0

@JamesWorld Где ваша версия Rx? – stromms

Смежные вопросы