2009-07-18 4 views
3

J'ai un tableau d'informations échantillon qui est constamment actualisé dans un thread d'arrière-plan.INotifyPropertyChanged et INotifyCollectionChanged dans F # en utilisant WPF

Actuellement, j'affecte constamment ce tableau à la propriété ItemsSource d'un flux de données à l'aide d'un DispatcherTimer. Cela fonctionne mais il réinitialise tous les emplacements visuels, par exemple si l'utilisateur place son curseur au milieu de la grille de données, le temporisateur d'exécution annulera cette position.

Est-il possible d'utiliser un événement INotifyPropertyChanged ou INotifyCollectionChanged à la place pour éviter que de telles situations se produisent? Si oui, comment cela fonctionne avec F #?

Je suppose que je dois exécuter une fonction notifiant la grille de données chaque fois qu'il y a une mise à jour du tableau. La mise à jour du tableau ne se trouve pas dans la section STAThread.

Je cours VS2010 avec la dernière boîte à outils WPF contenant la grille de données WPF.

Répondre

2

Vous pouvez utiliser une ObservableCollection qui implémente INotifyCollectionChanged pour vous. Le # F ressemble à ceci:

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) 

Malheureusement réflecteur montre que la méthode System.Windows.Controls.ItemsControl.OnItemCollectionChanged supprime la sélection lorsqu'elle est appelée, vous devrez peut-être contourner ce comportement par défaut.

Vous pouvez également mettre en œuvre INotifyPropertyChanged comme ceci:

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

mise en œuvre INotifyCollectionChanged fonctionnerait de la même.

bonne chance,

Danny

1

Les travaux de ObservableCollection mais malheureusement des problèmes. Etant donné que la fonction ObservableColection ne fonctionne que lorsqu'elle est modifiée dans STAThread, je dois utiliser un répartiteur et réécrire, ou au moins inspecter, le tableau complet, car je ne peux pas dire quelles entrées sont modifiées ou non.

Une chose qui est une possibilité est d'utiliser une boîte aux lettres F #. Le thread d'arrière-plan peut placer des messages de modification qui pourraient être récupérés par un répartiteur dans le STAThread. Cette solution supprimerait également le besoin de synchronisation.

Cela ressemble-t-il à une surcharge? Quelqu'un a déjà fait ça? Des solutions alternatives?