WPF обновляет TreeView, когда теряет фокус - PullRequest
0 голосов
/ 13 июля 2010

Из-за изменений, которые я внес в свой пост, я подумал открыть другую ветку.В новой ветке я выложил свое (временное) решение.Вы можете найти его здесь

Привет!У меня проблема с моим TreeView в приложении WPF (Framework 3.5 SP1).Это TreeVIew с 2 уровнями данных.Я раскрываю / сворачиваю элементы первого уровня определенным образом (одним щелчком мыши по TreeViewItem).Опять же, когда я раскрываю TreeViewItem первого уровня, я добавляю в группу несколько элементов TreeViewIte второго уровня (это важная деталь, если я не добавлю элементы, проблема не возникнет).Все работает хорошо, пока TreeView не потеряет фокус.Если, например, я разверну TreeViewItem в первой позиции, добавив одновременно один элемент ко второму уровню, то я нажму на кнопку (чтобы TreeView потерял фокус), а затем я снова нажму наTreeViewItem в третьей позиции, чтобы развернуть его, TreeViewItem, получаемый в результате проверки нажатия с помощью позиции мыши, - это не «настоящий» TreeViewItem (в данном случае третий), а TreeViewItem, который находится в более высокой позиции, чем нажатый(в данном случае второй).Я пытался использовать метод UpdateLayout для события TreeView-LostFocus, но безрезультатно.Вероятно, мне нужен метод, который делает противоположное: начиная с пользовательского интерфейса, обновите объект, который содержит позицию TreeViewItems.Не могли бы вы мне помочь?Спасибо!Pileggi

Это код:

   ' 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

Ответы [ 3 ]

0 голосов
/ 14 июля 2010

Спасибо, вы очень добры. Но, к сожалению, проблема та же с вашим решением. Я пропустил важную деталь (извините): когда я раскрываю TreeViewItem первого уровня, я добавляю TreeviewItems второго уровня. Это вызывает проблему, если я не добавляю элементы, все работает хорошо. Я отредактировал свой вопрос, чтобы сделать его более понятным. Может быть, теперь решение стало проще (надеюсь). Спасибо, Pileggi

0 голосов
/ 16 июля 2010

Из-за изменений, которые я внес в свой пост, я подумал открыть другую ветку.В новой ветке я выложил свое (временное) решение.Вы можете найти его здесь

0 голосов
/ 14 июля 2010

Ваш тестовый код попадания кажется немного странным.Вы игнорируете положение мыши, заданное объектом MouseButtonEventArgs, а затем выполняете тест на попадание в TreeView по верхнему левому углу элемента управления, по которому щелкнули.Обычно это снова возвращает вам тот же контроль, и я подозреваю, что ваше странное поведение происходит в тех случаях, когда это не так.Вместо использования TranslatePoint и InputHitTest, просто используйте отправителя напрямую.Ваша вспомогательная функция уменьшается до:

Private Function getParentOfType(Of childItem As DependencyObject)(ByVal sender As UIElement) As childItem
    Dim obj As DependencyObject = sender
    While obj Is Nothing = False AndAlso TypeOf obj Is childItem = False
        obj = VisualTreeHelper.GetParent(obj)
    End While
    Return DirectCast(obj, childItem)
End Function

Вы действительно можете снова упростить его, воспользовавшись тем, что MouseUp является перенаправленным событием и позволяет ему найти родителя TreeViewItem для вас.Вместо добавления обработчика событий к самому TreeView, добавьте обработчик MouseUp к TreeViewItem, и он всегда будет вызываться с отправителем TreeViewItem.

Вам также следует установить двустороннюю привязку IsExpanded, если это еще не сделано.Таким образом, вы можете обновить IsExpanded для TreeViewItem, и значение будет отправлено в источник привязки.

В XAML:

<TreeView.ItemContainerStyle>
    <Style TargetType="{x:Type TreeViewItem}">
        <Setter Property="IsExpanded" Value="{Binding isExpanded, Mode=TwoWay}" />
        <EventSetter Event="Mouse.MouseUp" Handler="tvi_MouseUp"/>
    </Style>
</TreeView.ItemContainerStyle>

Затем в коде:

Private Sub tvi_MouseUp(ByVal sender As System.Object, ByVal e As MouseButtonEventArgs)
    Dim tvi As TreeViewItem = DirectCast(sender, TreeViewItem)
    If tvi.HasItems Then
        tvi.IsExpanded = Not tvi.IsExpanded
    End If
    e.Handled = True
End Sub
...