从观察的集合中的视图模型删除不更新视图,但现有项目的更新不更新视图视图、模型、项目

2023-09-05 03:47:12 作者:当我们被一段感情伤过之后,会对爱情失望,甚至有些人决定余生不

我敢肯定,这将是一个扣篮的人... 手指交叉的

我的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.Horizo​​ntalScrollBarVisibility =隐藏
                  的Horizo​​ntalAlignment =拉伸VerticalAlignment =拉伸/>
 
4 1 视图模型是什么

视图模型:

 公共类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.P​​ractices.Prism.ViewModel

    公共类TileItem
        继承NotificationObject

        私人_created随着日期
        公共属性创建为日期
            得到
                返回_created
            最终获取
            套装(价值日期)
                _created =价值
                MyBase.RaisePropertyChanged(创建)
            结束设定
        高端物业

        私人_cat​​egory作为字符串
        公共属性类别作为字符串
            得到
                返回_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.