2009-07-18 24 views
3

私はバックグラウンドスレッドで常に更新されるサンプル情報の配列を持っています。WPFを使用して、F#でINotifyPropertyChangedとINotifyCollectionChangedを返します。

現在、この配列をDispatcherTimerを使用してDataGridのItemsSourceプロパティに割り当てています。それは動作しますが、例えば、ユーザがカーソルをデータグリッドの中央に置くと、実行タイマーはそのような位置を元に戻します。

このような状況が発生するのを防ぐために、代わりにINotifyPropertyChangedまたはINotifyCollectionChangedイベントを使用できますか?もしそうなら、F#でどのように動作しますか?

配列の更新があるたびにデータグリッドに通知する関数を実行する必要があると思います。配列の更新は、STAThreadセクションにはありません。

私はVS2010を、WPFデータグリッドを含む最新のWPFツールキットで実行しています。

答えて

2

あなたのためにINotifyCollectionChangedを実装するObservableCollectionを使用できます。 F#は、このようなものになります。

open System 
open System.Collections.ObjectModel 
open System.Windows 
open System.Windows.Controls 
open System.Windows.Threading 

[<EntryPoint; STAThread>] 
let Main args = 

    let data = ObservableCollection [0 .. 9] 
    let list = ListBox(ItemsSource = data)  
    let win  = Window(Content = list, Visibility = Visibility.Visible)  
    let rnd  = Random() 

    let callback = 
     EventHandler(fun sender args -> 
      let idx = rnd.Next(0, 10) 
      data.[idx] <- rnd.Next(0, 10) 
      ) 

    let ts = TimeSpan(1000000L) 
    let dp = DispatcherPriority.Send 
    let cd = Dispatcher.CurrentDispatcher 

    let timer = DispatcherTimer(ts, dp, callback, cd) in timer.Start()  
    let app  = Application() in app.Run(win) 

を不幸にリフレクターがSystem.Windows.Controls.ItemsControl.OnItemCollectionChanged方法は、それが呼び出された選択を削除することを示しているので、あなたは、このデフォルトの動作を回避する必要があるかもしれません。

また、そのようにINotifyPropertyChangedの実装できます。

open System.ComponentModel 

type MyObservable() = 

    let mutable propval = 0.0 
    let evt    = Event<_,_>() 

    interface INotifyPropertyChanged with 

     [<CLIEvent>] 
     member this.PropertyChanged = evt.Publish 

    member this.MyProperty 

     with get() = propval 
     and set(v) = propval <- v 
         evt.Trigger(this, PropertyChangedEventArgs("MyProperty")) 

実装INotifyCollectionChangedも同様に動作します。最高の幸運

ダニー

1

のObservableCollectionの作品が、残念ながら問題に。

ObservableColectionはSTAThreadで変更されたときにのみ機能するので、ディスパッチャーを使用して、基本的に完全な配列を書き直すか、少なくとも調べる必要があります。

可能性のあるものは、F#メールボックスを使用することです。バックグラウンドスレッドは、STAThread内のディスパッチャによって取得される可能性のある変更メッセージを配置する可能性があります。この解決策はまた、同期化の必要性を取り除く。

これは過度のようですか?誰も前にそれをやった?代替ソリューションはありますか?

関連する問題