У меня есть массив выборочной информации, которая постоянно обновляется в фоновом потоке.
В настоящее время я постоянно назначаю этот массив свойству ItemsSource сетки данных, используя DispatcherTimer. Это работает, но сбрасывает любые визуальные местоположения, например, если пользователь поместит свой курсор в середину сетки данных, таймер выполнения отменит эту позицию.
Можно ли вместо этого использовать событие INotifyPropertyChanged или INotifyCollectionChanged, чтобы предотвратить возникновение таких ситуаций? Если да, то как это работает с F#?
Я полагаю, что мне нужно выполнять некоторую функцию, уведомляющую сетку данных каждый раз, когда происходит обновление массива. Обновление массива не в разделе STAThread.
Я использую VS2010 с последним набором инструментов WPF, содержащим сетку данных WPF.
2 ответа
Вы можете использовать ObservableCollection, который реализует INotifyCollectionChanged для вас. 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 будет работать аналогично.
Удачи,
Дэнни
ObservableCollection работает, но, к сожалению, с проблемами.
Поскольку ObservableColection работает только при изменении в STAThread, мне приходится использовать диспетчер и в основном переписывать или, по крайней мере, проверять весь массив, поскольку я не могу сказать, какие записи изменены или нет.
Одной из возможных возможностей является использование почтового ящика F#. Фоновый поток может размещать сообщения об изменениях, которые могут быть получены диспетчером в STAThread. Это решение также устранит необходимость синхронизации.
Это похоже на излишество? Кто-нибудь делал это раньше? Любые альтернативные решения?
Похожие вопросы
Новые вопросы
wpf
Windows Presentation Foundation, или WPF, является подсистемой для визуализации пользовательских интерфейсов в приложениях на основе Windows.