问题
I have a problem with my TreeView in a WPF application (Framework 3.5 SP1). It's a TreeVIew with 2 Levels of Data. I expand / collapse the items of the first level in a particular way (with a single mouse-click on the TreeViewItem). Again when I expand a first-level TreeViewItem, I add some second-level TreeViewItems to the group (it's an important detail, infact if I don't add the items the problem doesn't occur). All works good until the TreeView loses focus. If, for example, I expand the TreeViewItem at the first position, adding at the same time one element to the second-level, then I click on a button (to let the TreeView lose the focus), and then I click again on the TreeViewItem at the third position to expand it, the TreeViewItem that results from the hit-test with the mouse position is not the "real" TreeViewItem (in this case the third), but a TreeViewItem which is in an higher position than the one clicked (in this case the second). I have tried to use the UpdateLayout method on the TreeView-LostFocus event, but without results. Probably I need a method that does the opposite: starting from the UI, refresh the object that contains the position of the TreeViewItems. Can you, please, help me? Thank you! Pileggi
This is the code:
' in this way I tried to put remedy at the problem, but it doesn't work.
Private Sub tvArt_LostFocus(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles tvArt.LostFocus
Me.tvArt.UpdateLayout()
e.Handled = True
End Sub
' here I expand / collapse the items of the first level of my TreeView
Private Sub tvArt_PreviewMouseUp(ByVal sender As System.Object, ByVal e As MouseButtonEventArgs) Handles tvArt.PreviewMouseUp
Dim p As Point = Nothing
Dim tvi As TreeViewItem = getItemFromMousePosition(Of TreeViewItem)(p, e.OriginalSource, Me.tvArt)
If tvi Is Nothing = False Then
If tvi.HasItems Then
Dim be As BindingExpression = BindingOperations.GetBindingExpression(tvi, TreeViewItem.ItemsSourceProperty)
Dim ri As P_RicambiItem = DirectCast(be.DataItem, P_RicambiItem)
If ri.isExpanded = False then
' here I add items to the second level collection
End If
ri.isExpanded = Not ri.isExpanded
End If
End If
e.Handled = True
End Sub
Private Function getItemFromMousePosition(Of childItem As DependencyObject)(ByRef p As Point, ByVal sender As UIElement, _
ByVal _item As UIElement) As childItem
p = sender.TranslatePoint(New Point(0, 0), _item)
Dim obj As DependencyObject = DirectCast(_item.InputHitTest(p), DependencyObject)
While obj Is Nothing = False AndAlso TypeOf obj Is childItem = False
obj = VisualTreeHelper.GetParent(obj)
End While
Return DirectCast(obj, childItem)
End Function
回答1:
I have find this solution (but I don't like it very much). The problem is depending from the added items that wpf, for some reasons, doesn't remember that exist. Then I do a "manual" refresh with a method that clear and re-add all the items in the source-collection:
Public Sub RefreshData(ByVal RicambiListPass As ObservableCollection(Of P_RicambiItem))
Dim l As New List(Of P_RicambiItem)
l.AddRange(RicambiListPass)
_RicambiList.Clear()
For Each i As P_RicambiItem In l
_RicambiList.Add(i)
Next
End Sub
来源:https://stackoverflow.com/questions/3245036/wpf-refresh-treeview-when-it-loses-the-focus