3

バックグラウンド スレッドで常に更新される一連のサンプル情報があります。

現在、DispatcherTimer を使用して、この配列をデータグリッドの ItemsSource プロパティに常に割り当てています。それは機能しますが、視覚的な場所をリセットします。たとえば、ユーザーがカーソルをデータグリッドの中央に置くと、実行タイマーがその位置を元に戻します。

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

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

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

4

2 に答える 2

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)

残念ながら、Reflector は 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 の実装も同様に機能します。

幸運を祈ります

ダニー

于 2009-07-18T23:20:13.193 に答える
1

ObservableCollectionは機能しますが、残念ながら問題があります。

ObservableColectionはSTAThreadで変更された場合にのみ機能するため、ディスパッチャーを使用して、どのエントリが変更されたかわからないため、基本的に配列全体を書き換えるか、少なくとも検査する必要があります。

可能性のあることの1つは、F#メールボックスを使用することです。バックグラウンドスレッドは、ディスパッチャがSTAThreadで取得できる変更メッセージを配置する可能性があります。このソリューションでは、同期の必要もなくなります。

それはやり過ぎのように見えますか?誰かが前にそれをしましたか?代替ソリューションはありますか?

于 2009-07-19T14:14:28.943 に答える