2011-12-30 2 views
7

から結合遅れは次のViewModelプロパティを考えてみましょう:Aはソース

テキストボックスにバインドされている
private string _slowProperty; 
public string SlowProperty 
{ 
    get { return _slowProperty; } 
    set 
    { 
     _slowProperty = value; 
     RaisePropertyChanged("SlowProperty"); 
    } 
} 

、そのよう:

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

は今、ここでの問題は、毎回というの値であり、 SlowPropertyが変更され、テキストボックスが非常に頻繁に行なわれ、その値を取得しようとすると、かなり遅くなります。しかし、非同期バインディングを使用して状況を緩和することはできますが、それでもCPUサイクルを無駄にすることになります。一定の遅延の後に結合するのを取得しよう

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

代わりに、私は何をしたいのですがすることのようなものがあります。たとえば、SlowPropertyが5回連続して変更された場合、しばらくの間、最後のテキストだけがテキストボックスに表示されます。

私はそのような何かを実行following projectを見つけたので、それは私の例私はそうのようにそれを使用することができます。

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

それに伴う問題は、それが後にのみ結合ターゲットを更新していることです遅れ。ただし、ソースパスは評価され、そのゲッターはソースの変更ごとに実行されます。これは、SlowPropertyの場合、CPUサイクルを無駄にします。

私は独自の遅延バインディングクラスを作成しようとしましたが、got stuckです。そんなことをすることができる他のバインダーはありますか? DelayBindingと同様のソリューション -

DeferredBinding:完全性期すため

、ここ2つの、他の同様のタスクを実行するプロジェクト、まだ、どれもアドレスの問題、私は経験していますがあります。しかし、それは少し複雑です。

DelayedBindingTextBox - カスタムテキストボックスコントロールを使用して遅延バインディングを実装します。

ありがとうございます!

答えて

3

ビューモデルでこの問題を解決してみませんか?あなたのプロパティが急速に変化するが、取得が遅い場合は、ビューモデルによって公開された2番目の「遅延」プロパティを持つことができます。タイマーを使用して、この「遅延」プロパティを定期的に更新することができます。

また、クリーンな実装では、リアクティブ・エクステンション・フレームワークによって提供される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という2つのマークアップ拡張を作成しました。あなたはUpdateSourceDelay

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

を指定するソースへの更新を遅らせるにはDelayBindingDelayMultiBindingのソースコードとサンプルの使用量がdownloaded hereすることができます。あなたは、実装の詳細に興味があるなら
、あなたはここでそれについての私のブログの記事をチェックアウトすることができます。注目すべき
DelayBinding and DelayMultiBinding with Source and Target delay

1

、純4.5のように、delay propertyができますフレームワークに追加されましたバインド遅延の量をミリ秒単位で設定します。 Microsoftの例では、twowayモードが強調されていますが、バインディング遅延はどのバインディングモードでも機能します。

たとえば、これはデータグリッドで使用しました。これは、選択した項目/値をカスタムのユーザーコントロール内のテキストボックスと明らかにデータグリッド内から変更する必要がありました。ここでは言及しない理由のため、テキストボックスはビューモデルとは異なるプロパティにバインドする必要がありましたが、両方のプロパティは終わりに同じ値を持たなければならず、そのいずれかの変更がもう一方に反映されます。 DataGridで選択された値が変更された場合、テキストボックスも更新する必要があり、無限ループを防ぐためにSelectedValueバインドプロパティのセッターで実際の値の変更を確認しました。変更が速すぎると、SelectedValueセッターによって変更されたテキストボックス内でテキストが変更されたときに、データを元に戻す際にエラーが発生しました。

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

これは非常に便利ですし、あなたにビューモデルのどのような変更を実装する手間を節約し、不必要に煩雑にする:2つのフレーム遅延は、任意の複雑なソリューションせずに、あまりにもラグのUI感じることなく問題を修正しましたコードは、ウィンドウを閉じる際にタイマーを処理する必要があります。もちろん、私のような比較的複雑なシナリオでも使用する必要はありませんが、UIの小さな変更ごとにCPU /リソース重いコードが不必要に実行されるのを防ぐのに役立ちます。

関連する問題