2014-12-03 2 views
3

나는 모든 viewModel이 INotifyPropertyChanged (아래 참조)를 구현하는 NotifyPropertyChangeClass 클래스에서 상속받은 wpf 응용 프로그램을 가지고 있습니다.버퍼 PropertyChanged 이벤트

알림이 너무 많이 전송되어 지연되는 것을 방지하기 위해보기로 보낸 알림을 제한하려고합니다. 지금까지 달성 한 것은 반응성 확장의 Sample 메서드를 사용하여 각 속성을 지연하는 것입니다.

문제는 Gui가 throttlingPeriod에 의해 늦게 새로 고쳐집니다.

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

@ 토마스 - 내가 한 Rx 버전은 그 상태를 관리해야하는 것을 피해야합니다. –

+0

@JamesWorld Rx 버전은 어디에 있습니까? – stromms

관련 문제