I encountered a curious issue while working on ImageListView. In the layout code of the control, I have a check to determine whether to show the vertical scrollbar. If the scrollbar needs to be shown, the layout is recalculated since the display area will be smaller with the scrollbar shown. However, my layout code ended up being called infinitely resulting in a stack overflow eventually. Here is the relevant part of the layout code.
1 public void UpdateLayout()
2 {
3
4
5
6
7 int cols = displayBounds.Width / itemSize.Width;
8 int rows = displayBounds.Height / itemSize.Height;
9
10
11 bool vScrollRequired = (cols * rows < items.Count);
12 if (vScrollBar.Visible != vScrollRequired)
13 {
14
15 vScrollBar.Visible = vScrollRequired;
16
17
18 UpdateLayout();
19 return;
20 }
21
22
23
24 }
The problem was with line 12 above. The Visible
property of the scrollbar always returned false
, if the layout code was called before the parent control is displayed. This is because -as I learned the hard way-, the getter of the Control.Visible property checks whether its parent control is visible
. If not, it will return false
regardless of what you set.
The solution was simple though. Keep a separate variable to track scrollbar’s visibility rather than relying on Control.Visible
.
Here is what I do not get. If the Visible
property actually means “the control is displayed on the screen”, then why does it return true
when the control is hidden under another control, or the control is moved beyond the client area of its parent?
ToolStripItem circumvents the issue by introducing the Available property. In the remarks section, MSDN says:
The Available
property is different from the Visible
property in that Available
indicates whether the ToolStripItem
is shown, while Visible
indicates whether the ToolStripItem
and its parent are shown. Setting either Available
or Visible
to true
or false
sets the other property to true
or false
.
This is what Control.Visible
should be doing in the first place. To determine if the control is actually displayed on the screen, there should have been another read-only
property (IsDisplayed
perhaps?).
It may not be possible to fix Control.Visible
since there are probably many applications relying on the current behavior. However, it should be possible to extend ToolStripItem.Available
property to the Control
class without causing many compatibility issues.