Обработка событий .Net Treeview - PullRequest
3 голосов
/ 04 августа 2010

Я нахожусь в процессе миграции приложения VB6 на .Net, и мы должны всегда обеспечивать функциональность, похожую на аналогичную.В одной форме это древовидное представление с флажками, которое имеет три уровня узлов.Первый уровень служит только для группировки следующего уровня вниз, и они не подлежат проверке.Узлы второго уровня могут быть проверены пользователем, и когда отмечены или сняты флажки, все его дочерние элементы следуют его примеру.На всех уровнях щелчок по узлу или его флажку означает, что он становится выбранным, независимо от того, затронуто или нет состояние проверки.

Третий уровень - это суть проблемы (хотя сама проблема проявляется на всехфлажки дерева): этот уровень содержит два «типа» узла, один из которых может быть проверен и не проверен пользователем (если установлен родительский элемент), и один тип, который не может быть проверен или не проверен пользователем независимо от состояния родительского элемента, но его состояние отражает состояние его родителя.

При обычном использовании все это работает как положено.Однако, если вы быстро щелкнете один из узлов третьего уровня (который не должен проверяться напрямую) дважды, он, похоже, изменит свое состояние проверки.Но если вы изучите базовое значение свойства Checked, оно останется неизменным, поэтому кажется, что это просто проблема отображения.Если обнаружится, эта аномалия станет проблемой для наших клиентов, так как пользователи могут подумать, что они могут сделать что-то, что они не могут привести к дорогостоящей путанице.

Я новичок в этом вопросе - кто-нибудь еще наблюдал такое поведение?или знаете об этом и есть ли обходные пути / решения для этого?Я не могу не чувствовать, что пропустил нечто действительно очевидное, но через полтора дня у меня теперь есть туннельное зрение.Вот некоторый код, чтобы продемонстрировать проблему.Создайте форму с древовидным представлением (достаточно большим, чтобы увидеть, что происходит) и двумя кнопками, а затем вставьте ее:

Private _node As TreeNode = Nothing


Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    MessageBox.Show(_node.Text & " : " & _node.Checked.ToString)
    _node = Nothing

End Sub

Private Sub InitialiseTreeview()

    TreeView1.Nodes.Clear()

    Dim ran As New Random
    Randomize()

    For i As Int32 = 1 To 5
        Dim TLNode As New TreeNode
        Dim children As Int32 = 0

        children = ran.Next(1, 5)

        TLNode.Text = "Top Level Node " & i.ToString

        For j As Int32 = 1 To children
            TLNode.Nodes.Add("Child Node " & j.ToString)
        Next

        TreeView1.Nodes.Add(TLNode)
    Next

    TreeView1.ExpandAll()
End Sub

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    InitialiseTreeview()
End Sub


Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    InitialiseTreeview()
End Sub

Запустите ее и нажмите на узел РАЗ.Нажмите кнопку 1, и она сообщит вам текст узла и его проверенное состояние.Теперь дважды установите флажок в одном и том же узле, быстро отметьте состояние флажка и снова нажмите кнопку 1.Вы поймете, что я имею в виду.Кнопка 2 генерирует новый набор узлов дерева.

1 Ответ

5 голосов
/ 04 августа 2010

Да, это ошибка, представленная версией Vista собственного элемента управления TreeView.Когда он видит событие двойного щелчка, он автоматически переключает состояние проверки элемента.Не сообщая об этом .NET TreeView обертку, событие Before / AfterCheck не будет запущено.Это не было исправлено в оболочке .NET и, вероятно, никогда не будет.

Чтобы обойти эту ошибку, нужно не допустить, чтобы встроенный элемент управления увидел сообщение двойного щелчка.Добавьте новый класс в ваш проект и вставьте код, показанный ниже.Компиляция.Перетащите новый элемент управления из верхней части панели инструментов на форму, заменив существующий TreeView.

Public Class MyTreeView
    Inherits TreeView

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        '' Filter the WM_LBUTTONDBLCLK message
        If m.Msg <> &H203 Then MyBase.WndProc(m)
    End Sub

End Class
...