我敢肯定,这将是一个扣篮的人... 手指交叉的
我的ListView的ItemsSource绑定到我的视图模型命名TileItems一个属性。
完美填充的列表视图更新。
在视图模型,在那里可以看到existingTileItem.Transaction = e.Transaction。 。 。个人ListView项完全更新。
在视图模型,在那里可以看到Me.TileItems.Remove(existingTileItem)...的项目不会从视图中删除。它成功地从Me.TileItems集合中移除,但更新未在视图中描绘
附加信息:AbstractViewModel实现INotificationPropertyChanged,我已经试过首要等于在TileItem,而不是覆盖它,同样的结果各地发生。我所看到的this回答和这的答案,但他们没有回答我有问题。
XAML:
< UserControl.DataContext>
<地方:TransactionTileResultsViewControlViewModel />
< /UserControl.DataContext>
< ListView控件Grid.Row =1NAME =tileItems的ItemsSource ={结合TileItems,模式=双向}
ItemTemplate中={的StaticResource tileItemDataTemplate}ScrollViewer.HorizontalScrollBarVisibility =隐藏
的HorizontalAlignment =拉伸VerticalAlignment =拉伸/>
视图模型:
公共类TransactionTileResultsViewControlViewModel
继承AbstractViewModel
实现INavigationAware
私人_tileItems作为TileItems
公共属性TileItems作为TileItems
得到
返回Me._tileItems
最终获取
套装(价值TileItems)
Me._tileItems =价值
MyBase.RaisePropertyChanged(TileItems)
结束设定
高端物业
....
#REGIONTransactionUpdateReceived方法
私人小组TransactionUpdateReceived_Handler(BYVAL E上TransactionUpdatedEvent)
如果e.Transaction状态并没有任何然后
昏暗existingTileItem作为TileItem = Me.TileItems.Where(功能(T)t.Transaction.TransactionQueueID = e.Transaction.TransactionQueueID).FirstOrDefault()
如果existingTileItem状态并没有任何然后
如果e.Transaction.Canceled然后
Me.TileItems.Remove(existingTileItem)
其他
如果e.Transaction.ContainsFailedActivites()OrElse运算e.Transaction.ContainsCallbackActivities(),然后
existingTileItem.Transaction = e.Transaction
其他
Me.TileItems.Remove(existingTileItem)
结束如果
结束如果
结束如果
结束如果
结束小组
#END地区
末级
TileItems型号:
公共类TileItems
(作者TileItem)继承的ObservableCollection
末级
TileItem型号:
进口Microsoft.Practices.Prism.ViewModel
公共类TileItem
继承NotificationObject
私人_created随着日期
公共属性创建为日期
得到
返回_created
最终获取
套装(价值日期)
_created =价值
MyBase.RaisePropertyChanged(创建)
结束设定
高端物业
私人_category作为字符串
公共属性类别作为字符串
得到
返回_category
最终获取
设置(值作为字符串)
_category =价值
MyBase.RaisePropertyChanged(类别)
结束设定
高端物业
私人_tileField1作为字符串
公共属性TileField1作为字符串
得到
返回_tileField1
最终获取
设置(值作为字符串)
_tileField1 =价值
MyBase.RaisePropertyChanged(TileField1)
结束设定
高端物业
私人_tileField2作为字符串
公共属性TileField2作为字符串
得到
返回_tileField2
最终获取
设置(值作为字符串)
_tileField2 =价值
MyBase.RaisePropertyChanged(TileField2)
结束设定
高端物业
私人_tileField3作为字符串
公共属性TileField3作为字符串
得到
返回_tileField3
最终获取
设置(值作为字符串)
_tileField3 =价值
MyBase.RaisePropertyChanged(TileField3)
结束设定
高端物业
私人_transaction作为交易
公共产权交易作为交易
得到
返回_transaction
最终获取
设置(值作为交易)
_transaction =价值
MyBase.RaisePropertyChanged(交易)
结束设定
高端物业
公共重写功能等于(OBJ作为对象)作为布尔
如果TypeOf运算obj是TileItem然后
昏暗tileItem作为TileItem = DirectCast(OBJ,TileItem)
如果tileItem.Transaction IsNot运算没有AndAlso Me.Transaction状态并没有任何然后
返回tileItem.Transaction.TransactionQueueID = Me.Transaction.TransactionQueueID
其他
返回False
结束如果
其他
返回False
结束如果
端功能
末级
更新:
每@ReedCopsey的答案,这里是我做得到这个工作的最新情况。
我更新Me.TileItems.Remove(existingTileItem)是这样的,现在
Me.View.Dispatcher.Invoke(子()
Me.TileItems.Remove(existingTileItem)
完子,DispatcherPriority.ApplicationIdle)
解决方案
在code你应该粘贴工作,从我所看到的。最有可能的罪魁祸首是你的 TransactionUpdateReceived
事件正在引发一个线程,是不是用户界面线程。在WPF中,单件商品可以修改在后台线程,但集不能(早于.NET 4.5,但是在.NET 4.5中,他们需要额外的工作)。
有两种选择。如果您使用的是.NET 4.5,您可以使用 BindingOperations .EnableCollectionSynchronization
让的ObservableCollection
从后台线程修改。
另外,你可以使用 Dispatcher.Invoke
来调用push添加/删除到主线程。
I'm sure this will be a slam dunk for someone... fingers crossed
My ListView ItemsSource is bound to a Property on my ViewModel named TileItems.
Populating the list view updates perfectly.
In the ViewModel, where you see "existingTileItem.Transaction = e.Transaction" . . . The individual listview item updates perfectly.
In the ViewModel, where you see "Me.TileItems.Remove(existingTileItem)" ... The item is not removed from the View. It does successfully remove from the Me.TileItems collection, but the update is not depicted in the View.
Additional Info: AbstractViewModel implements INotificationPropertyChanged, I've tried overriding Equals in the TileItem and not overriding it, and the same results all around happen. I have seen this answer and this answer, but they do not answer the issue I am having.
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:
Per @ReedCopsey 's answer, here is the update I made to get this working.
I updated Me.TileItems.Remove(existingTileItem) to be this now
Me.View.Dispatcher.Invoke(Sub()
Me.TileItems.Remove(existingTileItem)
End Sub, DispatcherPriority.ApplicationIdle)
解决方案
The code you're pasting should work, from what I can see. The most likely culprit is that your TransactionUpdateReceived
event is being raised on a thread that is not the user interface thread. In WPF, single items can be modified on a background thread, but collections cannot (prior to .NET 4.5, but in .NET 4.5, they require extra work).
There are two options. If you're using .NET 4.5, you can use BindingOperations.EnableCollectionSynchronization
to allow the ObservableCollection
to be modified from a background thread.
Alternatively, you can use Dispatcher.Invoke
to push the Add/Remove calls onto the main thread.