TL;DR: Need a way to disable scrolling in a TreeView
temporarily without any flickering.
Coding a C# plugin. I have a TreeView
control that displays a list of files open in an editor application.
The TreeView is part of a UserControl
loaded by the application and handles events called by the application, such as file change, upload to a server, etc.
I have the MouseEnter
and MouseLeave
events handled.
The MouseEnter
sets the focus to the TreeView, which is needed so that the double-click on the node works correctly (i.e. the application gives the input only after a mouse-click, which means a double-click becomes a single click; additionally a right-click if the mouse was moved sometimes returned the wrong node). With the focus set at the MouseEnter all works as expected.
The MouseLeave
hides any custom tooltip shown.
The problem that I have not been able to solve however is a problem with scrolling. If the number of nodes in the TreeView are too many, the TreeView needs to be scrolled. I am using the EnsureVisible()
method to achieve the necessary scrolling to the currently active file in the editor application. This part works perfectly.
The problem comes about when the user is scrolling with the mouse wheel while the mouse is not in the area of the TreeView. And it is a problem because MouseEnter sets the focus to the TreeView so that even if the scroll is done while the mouse pointer is in the active document, the focus being in the TreeView scrolls the TreeView, which is not wanted. (Scrolling with the scroll bar is okay, of course, since the user intends to scroll the TreeView.)
I tried more avenues to handle this but none of them is adequate:
- The first was to try to handle the MouseWheel event. But the problem
is that I found no way to prevent the scroll from executed, since
the
MouseEventArgs
do not have aCancel
field, and theDelta
field is read-only. So this did not help. Here is the code for the event handler:
private void treeView1_MouseWheel(object sender, MouseEventArgs e)
{
if (!(this.Width > e.Location.X &&
-1 < e.Location.X &&
this.Height > e.Location.Y &&
-1 < e.Location.Y))
{
//this is where the cancel should go;
return;
}
}
- The other avenue that I tried and I somewhat managed to handle this
problem with is to set the
Scrollable
property tofalse
in theMouseLeave
event handler and I set it totrue
in theMouseEnter
. This does the trick, but it has the side effect that change to theScrollable
property automatically calls theRecreateHandle()
method of theControl
class and because the nodes collapse this causes a flicker. Here is the code for the two event handlers:
private void treeView1_MouseEnter(object sender, EventArgs e)
{
treeView1.BeginUpdate();
treeView1.Focus();
treeView1.Scrollable = true;
treeView1.ExpandAll();
treeView1.EndUpdate();
}
private void treeView1_MouseLeave(object sender, EventArgs e)
{
//this first part of the code turns of the custom tooltip if certain conditions are true
if ((_mousePosOrig.Y - MousePosition.Y < 0 | MousePosition.Y - _mousePosOrig.Y < 15)
& Math.Abs(MousePosition.X - _mousePosOrig.X) < 30
& Math.Abs(MousePosition.Y - _mousePosOrig.Y) < 25) { }
else
{
toolTip1.RemoveAll();
_IstoolTipOn = false;
}
//here we turn of the scrolling
treeView1.BeginUpdate();
treeView1.Scrollable = false;
treeView1.ExpandAll();
treeView1.EndUpdate();
}
As you can see, I tried the BeginUpdate()
method, but it does not cure the flicker either.
Can anyone please help resolving this? Either giving me a clue on how to handle the flicker or on how to disable the scroll in some other way.