Remove from collection Observable in ViewModel does not update View, but updates to existing items update View

I'm sure for some it will be cotton ... fingers crossed

ListView ListSource elements are bound to the ViewModel property named TileItems.

Fully update your watch list.

In the ViewModel, where you see "existingTileItem.Transaction = e.Transaction"., The listview element is updated perfectly.

In the ViewModel, where you see "Me.TileItems.Remove (existingTileItem)" ... The item is not removed from the view. It is successfully removed from the Me.TileItems collection, but the update does not appear in the view.

Additional info: AbstractViewModel implements INotificationPropertyChanged, I tried to redefine Equals in TileItem, but not redefine it, and all the same results happen everywhere. I saw this answer and this answer, but they do not answer the question that I have.

XAML:

<UserControl.DataContext> <local:TransactionTileResultsViewControlViewModel /> </UserControl.DataContext> <ListView Grid.Row="1" Name="tileItems" ItemsSource="{Binding TileItems, Mode=TwoWay}" ItemTemplate="{StaticResource tileItemDataTemplate}" ScrollViewer.HorizontalScrollBarVisibility="Hidden" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" /> 

ViewModel:

 Public Class TransactionTileResultsViewControlViewModel Inherits AbstractViewModel Implements INavigationAware Private _tileItems As TileItems Public Property TileItems As TileItems Get Return Me._tileItems End Get Set(value As TileItems) Me._tileItems = value MyBase.RaisePropertyChanged("TileItems") End Set End Property '.... #Region "TransactionUpdateReceived Methods" Private Sub TransactionUpdateReceived_Handler(ByVal e As TransactionUpdatedEvent) If e.Transaction IsNot Nothing Then Dim existingTileItem As TileItem = Me.TileItems.Where(Function(t) t.Transaction.TransactionQueueID = e.Transaction.TransactionQueueID).FirstOrDefault() If existingTileItem IsNot Nothing Then If e.Transaction.Canceled Then Me.TileItems.Remove(existingTileItem) Else If e.Transaction.ContainsFailedActivites() OrElse e.Transaction.ContainsCallbackActivities() Then existingTileItem.Transaction = e.Transaction Else Me.TileItems.Remove(existingTileItem) End If End If End If End If End Sub #End Region End Class 

TileItems Model:

 Public Class TileItems Inherits ObservableCollection(Of TileItem) End Class 

TileItem Model:

  Imports Microsoft.Practices.Prism.ViewModel Public Class TileItem Inherits NotificationObject Private _created As Date Public Property Created As Date Get Return _created End Get Set(value As Date) _created = value MyBase.RaisePropertyChanged("Created") End Set End Property Private _category As String Public Property Category As String Get Return _category End Get Set(value As String) _category = value MyBase.RaisePropertyChanged("Category") End Set End Property Private _tileField1 As String Public Property TileField1 As String Get Return _tileField1 End Get Set(value As String) _tileField1 = value MyBase.RaisePropertyChanged("TileField1") End Set End Property Private _tileField2 As String Public Property TileField2 As String Get Return _tileField2 End Get Set(value As String) _tileField2 = value MyBase.RaisePropertyChanged("TileField2") End Set End Property Private _tileField3 As String Public Property TileField3 As String Get Return _tileField3 End Get Set(value As String) _tileField3 = value MyBase.RaisePropertyChanged("TileField3") End Set End Property Private _transaction As Transaction Public Property Transaction As Transaction Get Return _transaction End Get Set(value As Transaction) _transaction = value MyBase.RaisePropertyChanged("Transaction") End Set End Property Public Overrides Function Equals(obj As Object) As Boolean If TypeOf obj Is TileItem Then Dim tileItem As TileItem = DirectCast(obj, TileItem) If tileItem.Transaction IsNot Nothing AndAlso Me.Transaction IsNot Nothing Then Return tileItem.Transaction.TransactionQueueID = Me.Transaction.TransactionQueueID Else Return False End If Else Return False End If End Function End Class 

UPDATE:

In response to @ReedCopsey, here is the update I made to get this working.

I updated Me.TileItems.Remove (existingTileItem) to be it now

 Me.View.Dispatcher.Invoke(Sub() Me.TileItems.Remove(existingTileItem) End Sub, DispatcherPriority.ApplicationIdle) 
+4
source share
1 answer

The code you paste should work as I see it. The most likely culprit is that your TransactionUpdateReceived event is TransactionUpdateReceived on a thread that is not a UI thread. In WPF, individual elements can be changed in the background thread, but collections cannot (prior to .NET 4.5, but require additional work in .NET 4.5).

There are two options. If you are using .NET 4.5, you can use BindingOperations.EnableCollectionSynchronization to allow the ObservableCollection be changed from the background thread.

Alternatively, you can use Dispatcher.Invoke to push Add / Remove Calls to the main thread.

+7
source

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


All Articles