INotifyPropertyChanged and INotifyCollectionChanged in F # using WPF

I have an array of sample data that is constantly being updated in the background thread.

Currently, I am constantly assigning the datagrid ItemsSource property to this array using DispatcherTimer. This works, but it resets any visual locations, for example, if the user places his cursor in the middle of the datagrid, the execution timer will cancel this position.

Is it possible to use this INotifyPropertyChanged or INotifyCollectionChanged event to prevent such situations? If so, how does this work with F #?

I suggest that I have to execute some function that notifies the datagrid every time there is an array update. Updating the array is not in the STAThread section.

I am running VS2010 with the latest WPF toolkit containing the WPAT datagrid.

+3
source share
2 answers

You can use an ObservableCollection, which will implement INotifyCollectionChanged for you. 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 the System.Windows.Controls.ItemsControl.OnItemCollectionChanged method removes the selection when it is called, so you might need to bypass this default behavior.

You can also implement INotifyPropertyChanged as follows:

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

The implementation of INotifyCollectionChanged will work in a similar way.

good luck

Danny

+2
source

ObservableCollection , , , .

ObservableColection STAThread, , , , , .

, , - F #. , STAThread. .

? - ? ?

+1

Source: https://habr.com/ru/post/1712937/


All Articles