Этот вопрос покажется очевидным тем, кто сам не сталкивался с проблемой.
Мне нужно обработать изменения выбора в VTV. У меня есть плоский список узлов. Мне нужно делать что-то со всеми выбранными в данный момент узлами всякий раз, когда
и т. д. Это наиболее распространенное и ожидаемое поведение, как и в проводнике Windows: когда вы выбираете файлы с помощью мыши и / или клавиатуры, на информационной панели отображаются их свойства. Больше мне ничего не нужно. И здесь я застрял.
Ниже приводятся некоторые из моих исследований.
Сначала я использовал OnChange. Казалось, что это работает хорошо, но я заметил какое-то странное мерцание и обнаружил, что в наиболее распространенном сценарии (выбран один узел, пользователь щелкает другой) OnChange запускается дважды:
Эта проблема была доступна в Google, поэтому я обнаружил, что люди используют OnFocusChange и OnFocusChanging вместо OnChange. Но этот способ работает только для одиночного выбора. С множественным выбором, перетаскиванием и клавишами навигации это не работает. В некоторых случаях события Focus даже не срабатывают (например, когда выбор снимается щелчком по пустому пространству).
Я провел некоторое исследование результатов отладки, чтобы узнать, как эти обработчики запускаются в различных сценариях. Я обнаружил, что это полный беспорядок без какого-либо видимого смысла или закономерности.
C OnChange
FC OnFocusChange
FCg OnFocusChanging
- nil parameter
* non-nil parameter
! valid selection
Nodes User action Handlers fired (in order)
selected
0 Click node FCg-* C*!
1 Click same FCg**
1 Click another C- FCg** C*! FC*
1 Ctlr + Click same FCg** C*!
1 Ctrl + Click another FCg** C*! FC*
1 Shift + Click same FCg** C*!
1 Shift + Click another FCg** C-! FC*
N Click focused selected C-! FCg**
N Click unfocused selected C-! FCg** FC*
N Click unselected C- FCg** C*! FC*
N Ctrl + Click unselected FCg** C*! FC*
N Ctrl + Click focused FCg** C*!
N Shift + Click unselected FCg** C-! FC*
N Shift + Click focused FCg** C-!
1 Arrow FCg** FC* C- C*!
1 Shift + Arrow FCg** FC* C*!
N Arrow FCg** FC* C- C*!
N Shift + Arrow (less) C*! FCg** FC*
N Shift + Arrow (more) FCg** FC* C*!
Any Ctrl/Shift + Drag (more) C*! C-!
0 Click empty -
1/N Click Empty C-!
N Ctrl/Shift + Drag (less) C-!
1 Ctrl/Shift + Drag (less) C-!
0 Arrow FCg** FC* C*!
Это довольно сложно читать. В двух словах говорится, что в зависимости от конкретного действия пользователя три обработчика (OnChange, OnFocusChange и OnFocusChanging) вызываются в случайном порядке со случайными параметрами. FC и FCg иногда никогда не вызываются, когда мне все еще нужно обработать событие, поэтому очевидно, что я должен использовать OnChange.
Но следующая задача: внутри OnChange я не могу знать, следует ли мне использовать этот вызов или ждать следующего. Иногда набор выбранных узлов является промежуточным и бесполезным, и его обработка вызывает мерцание графического интерфейса пользователя и / или нежелательные тяжелые вычисления.
Мне нужны только те вызовы, которые отмечены знаком "!" в таблице выше. Но отличить их изнутри нет возможности. Например: если я нахожусь в "C-" (OnChange, Node = nil, SelectedCount = 0), это может означать, что пользователь удалил выделение (тогда мне нужно обработать его) или что они щелкнули другой узел (тогда мне нужно подождать следующий вызов OnChange при формировании новой выборки).
В любом случае, я надеюсь, что в моем исследовании не было необходимости.Я надеюсь, что я упускаю что-то, что сделало бы решение простым и понятным, и что вы, ребята, собираетесь указать мне на это. Решение этой головоломки с использованием того, что у меня есть до сих пор, привело бы к ужасно ненадежной и сложной логике.
Заранее спасибо!