Этот вопрос покажется очевидным для тех, кто не сталкивался с проблемой самостоятельно.
Мне нужно обработать изменения выбора в VTV.У меня плоский список узлов.Мне нужно что-то делать со всеми выбранными в данный момент узлами всякий раз, когда
- Пользователь щелкает узел;
- Пользователь Shift / Ctrl-щелкает узел;
- Пользователь использует клавиши со стрелкамидля навигации по списку;
- Пользователь создает выделение, перетаскивая мышь
- Пользователь удаляет выделение, щелкая пустое место или щелкая Ctrl при щелчке по единственному выбранному узлу
и т. д.,Это наиболее распространенное и ожидаемое поведение, как и в Windows Explorer: когда вы выбираете файлы мышью и / или клавиатурой, на информационной панели отображаются их свойства.Мне не нужно ничего больше, чем это.И вот тут я застреваю.
Далее следуют некоторые мои исследования.
Сначала я использовал OnChange.Казалось, что это работает хорошо, но я заметил странное мерцание и обнаружил, что в наиболее распространенном сценарии (один узел выбран, пользователь нажимает другой), OnChange запускается дважды:
- Когда старыйузел не выбран.На данный момент выбор пуст.Я обновляю свой графический интерфейс, чтобы вместо всех свойств отображалась метка «ничего не выбрано».
- Когда выбран новый узел.Я снова обновляю свой графический интерфейс, чтобы показать свойства нового узла.Отсюда и мерцание.
Эта проблема была googleable, поэтому я обнаружил, что люди используют 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 при формировании новой выборки).
В любом случае, я надеюсь, что мое исследование было ненужным.Я надеюсь, что я упускаю что-то, что сделало бы решение простым и понятным, и что вы, ребята, собираетесь указать мне на это.Решение этой загадки с использованием того, что у меня есть, порождает ужасно ненадежную и сложную логику.
Заранее спасибо!