When is Control.Visible = true turns out to be false?
I have a C# WinForms project that's very wizard like in its functionality. The individual steps live on a class called StepPanel, which inherits from the Panel control, within the form and those panels are organized in an array.
What I've run into is that when UpdateUI() is called and walks the array, adjusts the wizards step title text for the current ste开发者_C百科p, it makes sure that all of the inactive steps are hidden, and ensures that the active step is visible, in the right spot, and is the right size.
Here's the code:
private void UpdateUI()
{
// If the StepIndex equals the array length, that's our cue
// to exit.
if (StepIndex == Steps.Length)
{
Application.Exit();
return;
}
for (var xx = 0; xx < Steps.Length; xx++)
{
if (xx == StepIndex)
{
if (!String.IsNullOrEmpty(Steps[xx].Title))
{
LabelStepTitle.ForeColor = SystemColors.ControlText;
LabelStepTitle.Text = Steps[xx].Title;
}
else
{
LabelStepTitle.ForeColor = Color.Red;
LabelStepTitle.Text =
Resources.UiWarning_StepTitleNotSet;
}
}
else
{
Steps[xx].Visible = false;
}
}
Steps[StepIndex].Top = 50;
Steps[StepIndex].Left = 168;
Steps[StepIndex].Width = 414;
Steps[StepIndex].Height = 281;
Steps[StepIndex].Visible = true;
SetNavigationButtonState(true);
}
When everything is said and done, Steps[StepIndex].Visible == false.
I'm still perplexed by this behavior because I was working less than 30 minutes ago.
If you set a parent/container control to Visible = false
then setting any child controls to Visible = true
will have no effect what so ever. The Visible
property of the child control will still be false
.
I don't know if it's what happens in this case since I don't know the structure of the controls but it seems to be a likely scenario.
To solve this you need to first set the parent/contianer control to Visible = true
and THEN the child control(s).
if (xx == StepIndex)
Is only going to be true and the end of the loop unless I am missing something.
There are several possibilities. When you attach a debugger on the line:
SetNavigationButtonState(true);
does Steps[StepIndex].Visible == true
? If so, then make sure that StepIndex
is actually the index you expected (not off by 1, and not reflecting the "previous" step). If you verify that the correct step is set to true, then you must be updating it somewhere else.
if Steps[StepIndex].Visible == false
right after you set it to true, then either the getter on the Visible property is returning based on some calculation or an event was triggered that is changing it back to false.
HTH.
I encountered same issue using MDIForm in VB.net and Sani Singh Huttunen explanation is correct for me.
I post this answer to give more explanations and also a specific solution or a work around.
When I click on a specific menu to load a new MDI Child form, my program excute following code
Dim frm As New FrmPaiement
frm.MdiParent = Me
Call frm.NewRecord()
Call ReorganizeControlTopPositions(frm.DataPanel)
frm.Show()
where FrmPaiement
is a Form class that originally contains a lot of controls and DataPanel
is central panel that contains all data TextBox, CheckBox, ComboBox and DateBox controls.
But these time, some controls are hidden in frm.NewRecord()
function.
ReorganizeControlTopPosition()
function is called to reduce gaps between remainding visible controls
For information, VB.Net code of ReorganizeControlTopPositions()
is following
Public Sub ReorganizeControlTopPositions(ctlContainer As Panel)
'Put all controls in a List(Of Control) and sort it on Top position
For Each ctl As Control In ctlContainer.Controls
lstControls.Add(ctl)
Next
lstControls.Sort(Function(x, y) x.Top.CompareTo(y.Top))
'Reduce gaps between 2 visibles controls
Dim iLastTop As Integer = -1
Dim nInvisible = 0
Dim iLastControlTop As Integer = 0
For Each ctl In lstControls
If nInvisible > 0 Then
If ctl.Visible Then
If ctl.Top = iLastControlTop Then
ctl.Top = iLastTop
Else
iLastControlTop = ctl.Top
ctl.Top = iLastTop + 32
End If
End If
End If
If ctl.Visible Then
iLastTop = ctl.Top
Else
nInvisible += 1
End If
Next
End Sub
EXPLANATION OF ERROR
Since ReorganizeControlTopPositions()
function is called before frm.Show()
function, MDI Child is hidden and in debug mode, ctl.Visible
contains always False
!
If initialisation code if changed so that ReorganizeControlTopPositions()
is called after frm.Show()
call, program runs correctly and ctl.Visible
contains "correct" value.
Dim frm As New FrmPaiement
frm.MdiParent = Me
Call frm.NewRecord()
frm.Show()
Call ReorganizeControlTopPositions(frm.DataPanel)
The only problem is that MDI Form is shortly (very quicly) displaying controls with gaps and a micro secund later without gaps.
The problem is linked to Microsoft implementation of Visible property.
Setting Visible
property seems to change visible value of control but getting Visible
value return only True
if Visible
property of control is True
and also all containers containing this control are visibles !
What is written on Control.Visible property on learn.microsoft.com is extremly confuse !!!
Return True
if the control and all its child controls are displayed; otherwise, false. The default is true.
The correct definition sould be
Return True
if the control and all its PARENT controls are displayed; otherwise, false. The default is true.
精彩评论