VirtualTreeView:正确处理选择更改 [英] VirtualTreeView: properly handling selection changes

查看:145
本文介绍了VirtualTreeView:正确处理选择更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题对于那些没有遇到问题的人来说似乎是显而易见的。

This question will seem obvious to those who haven't encountered the problem themselves.

我需要处理VTV中的选择更改。我有一个平面的节点列表。

I need to handle selection changes in VTV. I have a flat list of nodes. I need to do stuff with all currently selected nodes whenever


  1. 用户点击一个节点;

  2. 用户Shift / Ctrl单击一个节点;

  3. 用户使用箭头键导航列表;

  4. 用户通过拖动鼠标创建选择

  5. 用户通过单击空白空间删除选择,或按住Ctrl键单击唯一选择的节点

  1. User clicks a node;
  2. User Shift/Ctrl-clicks a node;
  3. User uses arrow keys to navigate the list;
  4. User creates selection by dragging the mouse
  5. User removes selection by clicking on empty space or Ctrl-clicking the only selected node

等。这是最常见和预期的行为,就像Windows资源管理器:当您使用鼠标和/或键盘选择文件时,信息面板显示其属性。我只需要这样的东西。
这是我被卡住的地方。

etc. It's the most common and expected behavior, just like Windows Explorer: when you select files with mouse and/or keyboard, the information panel shows their properties. I need nothing more than that. And this is where I get stuck.

我的一些研究如下。

起初我用了OnChange。它似乎工作正常,但我注意到一些奇怪的闪烁,我发现在最常见的情况(一个节点被选中,用户点击另一个)OnChange被触发两次:

At first I used OnChange. It seemed to work well, but I noticed some strange flickering and I found that in the most common scenario (one node is selected, the user clicks another one) OnChange is fired twice:


  1. 取消选择旧节点。此时选择为空。我刷新我的GUI以显示没有选择标签代替所有属性。

  2. 选择新节点时。我再次刷新我的GUI来显示新节点的属性。因此,闪烁。

这个问题是googleable,所以我发现人们使用OnFocusChange和OnFocusChanging而不是OnChange。但这种方式只适用于单次选择。通过多重选择,拖动选择和导航键不起作用。在某些情况下,焦点事件甚至不会触发(例如,当通过单击空白空间删除选择时)。

This problem was googleable, so I found that people use OnFocusChange and OnFocusChanging instead of OnChange. But this way only works for single selection. With multiple selection, drag-selection and navigation keys this doesn't work. In some cases Focus events don't even fire at all (e.g. when selection is removed by clicking empty space).

我做了一些调试输出研究,以了解这些处理程序在不同的情况下被解雇。我发现是一个完整的混乱,没有任何可见的感觉或模式。

I did some debug output study to learn how these handlers are fired in different scenarios. What I found out is a total mess without any visible sense or pattern.

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。

This is quite hard to read. In the nutshell it says that depending on the specific user action, the three handlers (OnChange, OnFocusChange and OnFocusChanging) are called in random order with random parameters. FC and FCg are sometimes never called when I still need the event handled, so it is obvious I have to use OnChange.

但是下一个任务是:在OnChange里面我可以不知道我应该使用这个电话还是等待下一个电话。有时,所选节点的集合是中间的和非有用的,并且处理它将导致GUI闪烁和/或不需要的重的计算。

But the next task is: inside OnChange I can't know if I should use this call or wait for the next one. Sometimes the set of selected nodes is intermediate and non-useful, and processing it will cause GUI flickering and/or unwanted heavy calculations.

我只需要标记的呼叫用!在上表中。但是没有办法将它们与内部区分开来。例如:如果我在C-(OnChange,Node = nil,SelectedCount = 0),可能意味着用户删除了选择(然后我需要处理它)或者他们点击另一个节点(然后我需要等待当新的选择形成时,下一个OnChange调用)。

I only need the calls that are marked with "!" in the table above. But there is no way to distinguish them from inside. E.g.: if I'm in "C-" (OnChange, Node = nil, SelectedCount = 0) it could mean that user removed selection (then I need to handle it) or that they clicked another node (then I need to wait for the next OnChange call when new selection is formed).

无论如何,我希望我的研究是不必要的。我希望我错过了一些可以使解决方案简单明了的东西,而且你们都会为我指出。解决这个难题使用我迄今为止将产生一些非常不可靠和复杂的逻辑。

Anyway, I hope my research was unnecessary. I hope that I'm missing out something that would make the solution simple and clear, and that you, guys, are going to point it out for me. Solving this puzzle using what I have so far would generate some terribly unreliable and complex logic.

提前感谢

推荐答案

ChangeDelay 属性设置为适当的,大于零的值(以毫秒为单位),例如 100 。这实现了Rob Kennedy在他的回答中建议的一次性定时器。

Set the ChangeDelay property to an appropriate, greater than zero value in milliseconds, e.g. 100. This implements the one-shot timer Rob Kennedy suggests in his answer.

这篇关于VirtualTreeView:正确处理选择更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆