2011-12-30 5 views
7

바인딩 지연 이제A는 다음 뷰 모델의 특성을 고려 소스

<TextBox Text="{Binding SlowProperty}" /> 

는, 여기에 문제가 될 때마다 값이 SlowProperty가 변경되면 텍스트 상자가 이동하여 값을 얻으려고 시도하는 경우가 매우 많습니다. 그러나 비동기 바인딩을 사용하여 상황을 완화 할 수는 있지만 여전히 CPU주기를 낭비 할 것입니다. 일정 지연 후 바인딩을 얻기 위해 노력할 것이다

<TextBlock Text="{z:DelayedSourceBinding SlowProperty}" /> 

:

대신, 내가 가지고 싶은 것은 같은입니다. 예를 들어 SlowProperty이 5 번 연속으로 변경되면 잠시 후 마지막 텍스트 만 텍스트 상자에 표시됩니다.

나는 그런 일을 수행하는 following project을 발견했습니다, 그래서 내 예를 들어 나는 그렇게처럼 사용할 수 있습니다

<TextBox Text="{z:DelayBinding Path=SearchText}" /> 

그것으로 문제는 그 후에 바인딩 대상를 업데이트한다는 것입니다 지연. 그러나 소스 경로는 평가되고 소스의 모든 변경시 해당 getter가 실행됩니다. 어느 SlowProperty의 경우 CPU 사이클을 낭비합니다.

지연 바인딩 클래스를 직접 만들려고했지만 got stuck. 거기에 그렇게 할 수있는 다른 바인더가 있습니까? DelayBinding에 유사한 솔루션 -

DeferredBinding : 완성도를 위해서

, 여기이 개 다른 유사한 작업을 수행 프로젝트, 아직 없음 주소 문제 내가 경험하고 있습니다. 그러나 사용하기가 조금 더 복잡합니다.

DelayedBindingTextBox - 사용자 지정 텍스트 상자 컨트롤을 사용하여 지연 바인딩을 구현합니다.

감사합니다.

답변

3

왜 뷰 모델에서이 문제를 해결하지 않습니까? 속성이 빠르게 변경되지만 속도가 느린 경우보기 모델에 의해 두 번째 '지연된'속성이 노출 될 수 있습니다. 타이머를 사용하여 '지연된'속성을 주기적으로 업데이트 할 수 있습니다.

또는 클리너 구현에서는 reactive extensions 프레임 워크에서 제공하는 Throttle 함수를 사용할 수 있습니다.

+0

콜린, 우수. 간접 접근법의 또 다른 계층을 추가하면 모든 CS 문제를 해결할 수 있습니다! :) –

+0

아마 맞을 것입니다. 실제로 VM 레벨에서 해결해야 할 문제입니다. 하지만, 필자는 설명 된 것과 같이 사용자 정의 바인딩을 수행 할 수 있는지 알고 싶습니다. – VitalyB

1

당신이 정말로 원하는 것은 RaisePropertyChanged()가 호출 될 시점을 지연시키는 것 같습니다.
그래서 나는 그것을 밖으로 시도하고, 여기에 솔루션입니다 :

XAML :

<StackPanel> 
    <TextBox Text="{Binding DelayedText, UpdateSourceTrigger=PropertyChanged}" /> 
    <TextBlock Text="{Binding DelayedText}" /> 
</StackPanel> 

는 C# :

public partial class MainWindow : Window, INotifyPropertyChanged 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
      this.DataContext = this; 
     } 

     private String m_DelayedText; 
     public String DelayedText 
     { 
      get 
      { 
       return m_DelayedText; 
      } 
      set 
      { 
       if (m_DelayedText != value) 
       { 
        String delayedText; 
        m_DelayedText = delayedText = value; 
        Task.Factory.StartNew(() => 
         { 
          Thread.Sleep(2000); 
          if (delayedText == m_DelayedText) 
          { 
           RaisePropertyChanged("DelayedText"); 
          } 
         }); 
       } 
      } 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 
     private void RaisePropertyChanged(String _Prop) 
     { 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs(_Prop)); 
      } 
     } 
    } 

당신은 그것을 RaisePropertyChanged("DelayedText")에 중단 점을 설정하여 작동하는지 확인할 수 있습니다

"그냥"속성에 대해 상당히 많은 코드처럼 보일 수 있다는 것을 알고 있습니다.
하지만 Resharper 등을 사용하여 런타임에 코드 스 니펫을 사용하거나 상용구 코드를 삽입 할 수 있습니다.
어쨌든, 그렇게 자주 필요하지 않을 것입니다.

또한 다른 방법 (예 : TextBox 조정)을 사용하려면 속성에 바인딩하는 모든 위치를 처리해야합니다.
이렇게하면 속성 설정자에서이 속성에 액세스하는 모든 사용자가 업데이트를 받도록 제한하게됩니다.

HTH,

bab.

+0

재미있는 솔루션, 감사합니다! 결과 코드에서는 실제로 약간 무거웠지만 흥미로운 읽기였습니다. – VitalyB

2

원본과 대상을 모두 지연시킬 필요가있는 곳에서 비슷한 요구 사항을 가지고 있으므로 DelayBindingDelayMultiBinding이라는 두 가지 태그 확장을 만들었습니다. 당신이 DelayBinding에 대한 UpdateSourceDelay

<TextBox Text="{db:DelayBinding SlowProperty, 
           UpdateSourceDelay='00:00:01'}" /> 

소스 코드 및 샘플 사용을 지정하고 DelayMultiBindingdownloaded here을 할 수있는 소스에 대한 업데이트를 지연합니다. 당신이 구현 세부 사항에 관심이 있다면
, 당신은 여기에 대한 내 블로그 게시물을 확인하실 수 있습니다 : 참고로
DelayBinding and DelayMultiBinding with Source and Target delay

1

, 닷넷 4.5과 같은 delay property이 할 수있는 프레임 워크에 추가되었습니다 바인딩 지연 량을 밀리 초 단위로 설정합니다. Microsoft 예제에서는 twoway 모드가 강조되지만 바인딩 지연은 모든 바인딩 모드에서 작동합니다.

예를 들어 선택한 항목/값을 사용자 지정 사용자 정의 컨트롤 내의 텍스트 상자와 분명히 데이터 그리드 내에서 변경해야하는 데이터 그리드에서이 값을 사용했습니다. 여기서는 언급하지 않기 때문에 텍스트 상자는 뷰 모델과 다른 속성에 바인딩해야했지만 둘 다 속성은 하루가 끝날 때 같은 값을 가져야했으며 둘 중 하나의 변경 사항이 있어야했습니다. 다른쪽에 반영. DataGrid에서 선택한 값이 변경되면 텍스트 상자도 업데이트되어야하며 무한 루프를 방지하기 위해 SelectedValue 바인드 된 속성의 setter에서 실제 값 변경 사항을 확인했습니다. 변경이 너무 빠 른 경우 SelectedValue 설정자가 변경 한 텍스트 상자 내에서 텍스트가 변경된 경우 데이터를 소스로 다시 저장하는 동안 오류가 발생했습니다.

SelectedValue="{Binding SampleNumberSelect, Mode=OneWayToSource, Delay=33}" 

이 매우 편리하고 당신에게 뷰 모델에서 이러한 변경을 구현하는 번거 로움을 저장, 불필요하게 난장판 것 : 두 개의 프레임 지연은 복잡한 솔루션없이 너무 랙이 UI를 느낌없이 문제를 해결 코드를 사용하여 창 닫기시 타이머를 처분해야합니다. 물론 내 것과 같이 비교적 복잡한 시나리오에서도 사용할 필요는 없지만 UI의 작은 변화가있을 때마다 CPU/리소스 무거운 코드가 불필요하게 실행되는 것을 방지하는 것이 도움이 될 수 있습니다.

관련 문제