3

我有一组在后台线程中不断刷新的示例信息。

目前,我经常使用 DispatcherTimer 将此数组分配给数据网格的 ItemsSource 属性。这可行,但它会重置任何视觉位置,例如,如果用户将光标放在数据网格的中间,则执行计时器将撤消该位置。

是否可以为此使用 INotifyPropertyChanged 或 INotifyCollectionChanged 事件来防止发生此类情况?如果是这样,这如何与 F# 一起使用?

我想每次更新数组时我都必须执行一些通知数据网格的函数。数组的更新不在 STAThread 部分。

我正在使用包含 WPF 数据网格的最新 WPF 工具包运行 VS2010。

4

2 回答 2

2

You can use an ObservableCollection which will implements INotifyCollectionChanged for you. The F# looks something like this:

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)

Unfortunately Reflector shows that System.Windows.Controls.ItemsControl.OnItemCollectionChanged method removes the selection when it is called, so you may need to work around this default behaviour.

You can also implement INotifyPropertyChanged like so:

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"))

Implementing INotifyCollectionChanged would work similarly.

best of luck,

Danny

于 2009-07-18T23:20:13.193 回答
1

ObservableCollection 有效,但不幸的是有问题。

由于 ObservableColection 仅在 STAThread 中修改时才有效,因此我必须使用调度程序并基本上重写或至少检查完整的数组,因为我无法判断哪些条目已更改。

可能的一件事是使用 F# 邮箱。后台线程可以放置可以由 STAThread 中的调度程序拾取的更改消息。该解决方案还将消除对同步的需要。

这看起来像矫枉过正吗?以前有人做过吗?任何替代解决方案?

于 2009-07-19T14:14:28.943 回答