我相信这对某人来说是一个扣篮...... 手指交叉
我的ListView ItemsSource绑定到我的ViewModel上名为TileItems的Property。
完美填充列表视图更新。
在ViewModel中,您可以看到“existingTileItem.Transaction = e.Transaction”。 。 。单个列表视图项目完美更新。
在ViewModel中,您可以看到“Me.TileItems.Remove(existingTileItem)”...项目未从视图中删除。它确实从Me.TileItems集合中成功删除,但视图中未描述更新。
附加信息:AbstractViewModel实现了INotificationPropertyChanged,我尝试在TileItem中覆盖Equals而不是覆盖它,并且所有周围都会发生相同的结果。我看到了this回答和this回答,但他们没有回答我遇到的问题。
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" />
视图模型:
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模型:
Public Class TileItems
Inherits ObservableCollection(Of TileItem)
End Class
TileItem模型:
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
更新
根据@ReedCopsey的回答,这是我为实现这一目标所做的更新。
我将Me.TileItems.Remove(existingTileItem)更新为现在
Me.View.Dispatcher.Invoke(Sub()
Me.TileItems.Remove(existingTileItem)
End Sub, DispatcherPriority.ApplicationIdle)
答案 0 :(得分:7)
从我所看到的,您正在粘贴的代码应该可以正常工作。最可能的罪魁祸首是您的TransactionUpdateReceived
事件是在不是用户界面线程的线程上引发的。在WPF中,可以在后台线程上修改单个项目,但是集合不能(在.NET 4.5之前,但在.NET 4.5中,它们需要额外的工作)。
有两种选择。如果您使用的是.NET 4.5,则可以使用BindingOperations.EnableCollectionSynchronization
来允许从后台线程修改ObservableCollection
。
或者,您可以使用Dispatcher.Invoke
将添加/删除调用推送到主线程。