4

我敢肯定这对某人来说将是一次扣篮……祈祷

我的 ListView ItemsSource 绑定到我的 ViewModel 上名为 TileItems 的属性。

填充列表视图会完美更新。

在 ViewModel 中,您会看到 "existingTileItem.Transaction = e.Transaction" 。. . 单个列表视图项目完美更新。

在 ViewModel 中,您会看到“Me.TileItems.Remove(existingTileItem)”...该项目不会从视图中删除。它确实从 Me.TileItems 集合中成功删除,但视图中未显示更新。

附加信息:AbstractViewModel 实现了 INotificationPropertyChanged,我已经尝试在 TileItem 中覆盖 Equals 而不是覆盖它,并且周围都发生了相同的结果。我已经看到了这个答案和这个答案,但他们没有回答我遇到的问题。

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

瓷砖项目型号:

Public Class TileItems
    Inherits ObservableCollection(Of TileItem)

End Class

瓷砖项目型号:

 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)
4

1 回答 1

7

据我所知,您粘贴的代码应该可以工作。最可能的罪魁祸首是您的TransactionUpdateReceived事件是在不是用户界面线程的线程上引发的。在 WPF 中,可以在后台线程上修改单个项目,但不能修改集合(在 .NET 4.5 之前,但在 .NET 4.5 中,它们需要额外的工作)。

有两种选择。如果您使用的是 .NET 4.5,则可以使用BindingOperations.EnableCollectionSynchronization允许ObservableCollection从后台线程进行修改。

或者,您可以使用Dispatcher.Invoke将 Add/Remove 调用推送到主线程。

于 2013-09-02T19:25:20.760 回答