I have an ObservableCollection that is using a FileSystemWatcher to automatically add other PNG images that have been added to the directories. The ListBox has the ItemsSource databound to the Photos object using the following XAML.
<ListBox ItemsSource="{Binding Source={StaticResource Photos}}" IsSynchronizedWithCurrentItem="True"/>
However when a PNG file is added to the monitored directory the OnPhotoCreated event is being called (a breakpoint confirms this) however the ListBox UI is not being updated. Any ideas?
Public Class Photos
Inherits Collections.ObjectModel.ObservableCollection(Of BitmapImage)
' Events
Public Event ItemsUpdated As EventHandler
' Fields
Private FileSystemWatchers As Dictionary(Of String, FileSystemWatcher) = New Dictionary(Of String, FileSystemWatcher)
' Methods
Protected Overrides Sub ClearItems()
MyBase.ClearItems()
Me.FileSystemWatchers.Clear()
End Sub
Protected Overrides Sub InsertItem(ByVal index As Integer, ByVal item As BitmapImage)
MyBase.InsertItem(index, item)
Dim ImagePath As String = IO.Path.GetDirectoryName(item.UriSource.LocalPath)
If Not Me.FileSystemWatchers.ContainsKey(ImagePath) Then
Dim FileWatcher As New FileSystemWatcher(ImagePath, "*.png")
FileWatcher.EnableRaisingEvents = True
AddHandler FileWatcher.Created, New FileSystemEventHandler(AddressOf Me.OnPhotoCreated)
AddHandler FileWatcher.Deleted, New FileSystemEventHandler(AddressOf Me.OnPhotoDeleted)
AddHandler FileWatcher.Renamed, New RenamedEventHandler(AddressOf Me.OnPhotoRenamed)
Me.FileSystemWatchers.Add(ImagePath, FileWatcher)
End If
End Sub
Private Sub OnPhotoCreated(ByVal sender As Object, ByVal e As FileSystemEventArgs)
MyBase.Items.Add(New BitmapImage(New Uri(e.FullPath)))
RaiseEvent ItemsUpdated(Me, New EventArgs)
End Sub
Private Sub OnPhotoDeleted(ByVal sender As Object, ByVal e As FileSystemEventArgs)
Dim index As Integer = -1
Dim i As Integer
For i = 0 To MyBase.Items.Count - 1
If (MyBase.Items.Item(i).UriSource.AbsolutePath = e.FullPath) Then
index = i
Exit For
End If
Next i
If (index >= 0) Then
MyBase.Items.RemoveAt(index)
End If
RaiseEvent ItemsUpdated(Me, New EventArgs)
End Sub
Private Sub OnPhotoRenamed(ByVal sender As Object, ByVal e As RenamedEventArgs)
Dim index As Integer = -1
Dim i As Integer
For i = 0 To MyBase.Items.Count - 1
If (MyBase.Items.Item(i).UriSource.AbsolutePath = e.OldFullPath) Then
index = i
Exit For
End If
Next i
If (index >= 0) Then
MyBase.Items.Item(index) = New BitmapImage(New Uri(e.FullPath))
End If
RaiseEvent ItemsUpdated(Me, New EventArgs)
End Sub
End Class
Update #1: I have tried an Event as shown below. That causes a crash with InvalidOperationException, "The calling thread cannot access this object because a different thread owns it" When the new image is attempted to scroll into view. I was hoping that the Refresh method would not be needed.
Dim Photos As Photos = CType(Me.FindResource("Photos"), Photos)
AddHandler Photos.ItemsUpdated, AddressOf Me.Photos_ItemsUpdated
Private Sub RefreshPhotos()
'
If Me.ImageListBox.Dispatcher.CheckAccess = True Then
Me.ImageListBox.Items.Refresh()
Else
Dispatcher.BeginInvoke(DispatcherPriority.Normal, New DispatcherMethodCallback(AddressOf Me.RefreshPhotos))
End If
'
End Sub
Private Sub Photos_ItemsUpdated(ByVal sender As Object, ByVal e As EventArgs)
'
Debug.WriteLine("PhotosUpdated")
Me.RefreshPhotos()
'
End Sub