2

FileSystemWatcherを使用して、ディレクトリに追加された他のPNG画像を自動的に追加するObservableCollectionがあります。 ListBoxには、次のXAMLを使用してPhotosオブジェクトにバインドされたItemsSourceデータがあります。 PNGファイルが監視対象ディレクトリに追加されたときにObservableCollection FileSystemWatcher ListBox更新の問題

<ListBox ItemsSource="{Binding Source={StaticResource Photos}}" IsSynchronizedWithCurrentItem="True"/> 

しかしOnPhotoCreatedイベントは、しかし、ListBoxのUIが更新されていない(ブレークポイントはこれを確認し)と呼ばれています。何か案は?

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 

更新#1:以下に示すように、私は、イベントを試してみました。そのため、InvalidOperationException、 "別のスレッドが所有しているため、呼び出し元のスレッドはこのオブジェクトにアクセスできません"というクラッシュが発生します。新しいイメージをスクロールして表示しようとすると、 Refreshメソッドが必要ないと私は望んでいました。

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 
+0

RaiseEvent ItemsUpdatedへの呼び出しがありますが、そのイベントで何かしていることはわかりません。何か不足していますか? – David

+0

私はそのイベントを試みましたが、期待どおりに動作しませんでした。私はPhotosクラスでリフレッシュを呼び出す必要がない何かをやりたいと思っていました。 – Luke

+0

上記のコードでUpdate#1を参照してください。 – Luke

答えて

1

(リフレクター)からのObservableCollectionクラスからのInsertItemコードを見てみましょう:

Protected Overrides Sub InsertItem(ByVal index As Integer, ByVal item As T) 
    Me.CheckReentrancy 
    MyBase.InsertItem(index, item) 
    Me.OnPropertyChanged("Count") 
    Me.OnPropertyChanged("Item[]") 
    Me.OnCollectionChanged(NotifyCollectionChangedAction.Add, item, index) 
End Sub 

は今のObservableCollectionをれる通知どのようなガイドラインが行う必要があることを使用します。 OnCollectionChangedメソッドは、wpf通知システムへの主な接続です。適切に呼び出されると、このcalssは正常に動作し、それ以外の場所で問題が発生します。

また、あなたのOnPhotoCreated方法では、あなたは、通知を行いませんItems.Addメソッドを呼び出し、それはのObservableCollectionクラスに属しているが、のObservableCollectionを継承するCollection<T>クラスはありません。

InvalidOperationExceptionエラーは、間違ったスレッドからUIへのUI更新のようです。