Visibility of Form Components when Enabled is false C# - c#

I have a form with labels and other components, picture boxes, panels, etc.. When I am doing Form.enabled = false; (because I have another form on top of it) the labels are not showing even though the visibility of the components is set to true; Any ideas?
I didn't include code because I'm not sure what to include!
Thanks for any help!
Edit: After what Joel Etherton said, I tried using this event:
private void label1_VisibleChanged(object sender, EventArgs e)
{
label1.Visible = true;
}
This is giving me a StackOverflowException.. maybe this is infinitely trying to override the parent control visibility.. What can I do please?

Check the element's parent objects (and follow it up the tree). Usually this is caused by a parent being set to Visible = false;. Visibility settings for a particular control will still register as true, but when the page is actually rendered it will stop producing controls at any parent level whose visibility is false.
Edit:
First you should find the root cause of the problem. This isn't a code issue so much as an expectation issue. A control is expected to be visible, but you've created a condition where that is not possible. I think you'd be better served by trying to find out what condition is causing a parent control to have a false visibility. Most likely you'll find either there is a logical problem with forcing a parent's visibility or a design problem where your "visible" control is being placed in the wrong root container. However, if you just want to brute force the visibility of parents you can have a recursive method do it:
private static void SetAllParentVisibility(bool visible, Control ctrl)
{
ctrl.Visible = visible;
if (ctrl.Parent != null)
SetAllParentVisibility(visible, ctrl.Parent);
}
Also, treat the above method as psuedo-code. I haven't tested it out, and the type Control may need to be altered to be able to adjust to different parent types.

Related

Control not visible after toggling visibility recursively?

A Quick Note
I've tried to be as thorough as possible with my question but you may still need additional clarification; if this happens to be the case, feel free to comment your concerns and I will update the post to answer them as best as I can.
I came across a rather odd issue yesterday when toggling controls on my form. I have a period of loading on FormShown and all controls but the loading display should be hidden. The toggle works to turn visibility off for everything but the loading display, but when loading completes only some of the controls are visible.
I stepped through the code that turns everything back to visible and ensured that everything is indeed being set to Visible = true. I think it may have something to do with the Dock property on the controls, or maybe the TabIndex or something similar but I'm having trouble tracking the underlying issue down.
This is the code I use to toggle the control visibility:
private void ToggleAllControlVisibility() {
foreach (Control c in Controls)
ToggleControlVisibility(c);
}
private void ToggleControlVisibility(Control c) {
if (c.Name == "loadingContainer")
return;
if (!(c is SplitContainer || c is SplitterPanel))
c.Visible = !c.Visible;
foreach (Control child in c.Controls)
ToggleControlVisibility(child);
}
It is a recursive toggle in which all child controls are also toggled. The ToggleAllControlVisibility method is called before loading begins, and again after loading completes.
A More Detailed Look
Now that you know the problem, there are certain controls in particular that I know do not show (at least the way they should). Take the following control tree for example:
pTimePanel (Panel)
timeSlider (TrackBar)
lblStartTime (Label)
lblStopTime (Label)
Out of the controls above, only the pTimePanel actually displays in the foreground. I believe its child controls may be displaying behind it somehow because as I step through the code and it reaches the lblStartTime control, I can briefly see the outline of the label (no content) and then when it moves to the next control it's gone. The timeSlider control doesn't seem to show the same behavior but it does get back to Visible = true.
The full tree from form to the above controls (with docking properties) is as below:
splitContainer : Dock-Fill
panel1 (SplitterPanel)
loadingPanel (Panel) : Dock-Fill
pTimePanel (Panel) : Dock-Bottom
pTimeLabels (Panel) : Dock-Bottom
lblStartTime (Label) : Dock-Left
lblStopTime (Label) : Dock-Right
timeSlider (TrackBar) : Dock-Fill
Notes
Some of these may be less helpful than others, but as I think of things that may help clarify what's going on, I'll add them here.
When visibility is toggled in either direction, the Resize event on the loadingPanel is raised.
Question
What could possibly be occurring to make this odd behavior possible?
It turns out that this was related to the order in which the controls were added to the form. Due to some copying and pasting controls a while back things ended up in an improper order. I had to rebuild the form from scratch to get any toggling to actually work. Once I rebuilt the form, all of the available options for toggling began working the way I expected them to.

How to override Control.Enabled property in C# Winforms?

I have a custom control I am working on. I want to change its color when it is enabled or disabled. So I wrote a code inside OnEnabledChanged.
protected override void OnEnabledChanged(EventArgs e)
{
if (!Enabled)
{
temp1 = colorOn;
temp2 = colorOff;
colorOff = colorOn = Color.LightGray;
}
else
{
colorOn = temp1;
colorOff = temp2;
}
Invalidate();
base.OnEnabledChanged(e);
}
This code works fine in runtime but not design time. It wasn't raised when I changed the Enabled property in design time. So I want to override the Enabled property of the control. But it doesn't show up when typing it.
So how can I override it? If there is another way I want to use it.
That is entirely normal. One job of a control designer is to intercept the behavior of certain properties and methods that interfere with the use of the control in the design view. The Enabled property is one of them, if that would work at design-time as well then you could never select the control again. The designer can't let that happen of course, it always forces Enabled = true at design time and intercepts assignments to the property. As you found out. Overriding it can work either, it is not a virtual property, but wouldn't give you what you want anyway. The Visible property is another one that's intercepted like that, you can imagine how that goes wrong :)
You would have to create your own designer to do something about it. This in general tends to be a bazooka to kill a mosquito, especially in this case since you still can't do anything with Enabled. And worse, this behavior is implemented by the ControlDesigner class, the kind of class you need as a base class to get a designer going. I seriously doubt it is practical.
Doing nothing at all to fix this is entirely reasonable, given that none of the other controls in the toolbox change their appearance either when you change their Enabled property in the designer.

How to refresh a winform custom control at design time after changing a property

Let's say I create a custom control which embed a trackbar. I also create an orientation property for my custom control.
When I drop the custom control on a form by default it will be horizontal. Then I set it to vertical, the trackbar should refresh to be vertical at design time.
How to do so ?
I think you should call Refresh() after changing the value:
public OrientationProperty Direction
{
get
{
return _direction;
}
set
{
_direction = value;
if (DesignMode)
{
Parent.Refresh(); // Refreshes the client area of the parent control
}
}
}
private OrientationProperty _direction;
Here's my solution to this issue:
1. Whenever you set something property, call Invalidate() in the setter.
2. After correspondent properties and refreshing method (for eg. overridden OnPaint) are implemented, rebuild!!! then you'll see the modifications taken effect in design time
3. During design, always check whether compilation errors are present, as this might stop VS performing all his tasks.
With this, when I put my control on a form, and adjust its own properties, refreshing happens immediately as expected.
PS.: old post, but at least verified the behavior in VS2015 too :)

Disabling a control from receiving a event in C#

I have a dialog with loads of control in it. Each and evey control will be populated during the loading sequence and it might take a while for it to get completely filled. Mean while, I don't wanna allow the user to click on any of the controls. In other words, I wanna disable the control from receiving the events and I don't wanna disable the controls (as it might look odd).Also, I don't wanna subscribe and unsubscribe for the events regular intervals. Is there any way to stop the controls from listening to the events for a brief time ??
Sudarsan Srinivasan
The whole point of disabling controls is to communicate to the user that the control cannot be used at a particular time. This is a convention that users have learned and are used to, so I would advice to follow that. Not doing that may confuse the users.
The easiest way is to disable the container in which the controls are located in, rather than disabling each and every control. A better way (or at least the way that I prefer) is to have a method that will control the Visible and Enabled properties of controls based on which state the UI is in.
The easiest way is to move the control population out of the load event (if possible). Then in Load do something like:
private bool _LoadComplete;
void OnFormLoad(Object sender, EventArgs e)
{
_LoadComplete = true;
InitializeControls();
_LoadComplete = false;
}
void InitializeControls()
{
// Populate Controls
}
void OnSomeControlEvent()
{
if (_LoadComplete)
{
// Handle the event
}
}
Edit A Couple other Ideas:
Set the Application.Cursor = WaitCursor (typically will disallow clicking, but not a 100% guarantee)
Create a "Spinner" control to let the user know that the screen is busy. When loading bring it to the front so it sits on top and covers all other controls. Once you're done loading set it to visible = false and show your other controls
Unfortunately the only way i know of is to have a class variable (called something like _loading) and in each control handler do something like:
If (! _loading )
{
...
}
And in your loading code set _loading = true; once you have finished loading.
If you just want to disable user input, then you can set the form's Enabled property to false.
This has the effect of blocking user input to any of the form's controls, without changing the appearance of the controls; it's the technique used internally by the ShowDialog method.

Controlling designer appearance of double-buffered owner-drawn UserControl in C#/.NET 2.0

I have an owner-drawn UserControl where I've implemented double-buffering. In order to get double-buffering to work without flicker, I have to override the OnPaintBackground event like so:
protected override void OnPaintBackground(PaintEventArgs e)
{
// don't even have to do anything else
}
This works great at runtime. The problem is that when I have an instance of the control on a form at design time, it becomes a black hole that shows trails of whatever windows are dragged over it (because the override of the OnPaintBackground event also governs design-time appearance). It's just a cosmetic problem, but it's visually jarring and it always leads new developers on the project to assume something has gone horribly wrong.
Is there any way to have an overridden method like this not be overridden at design time, or is there another solution?
Steven Lowe's solution unfortunately cover all scenarios, espcially when user controls come into the picture.
The this.DesignMode flag is very deceptive. Its only scope is to check if the direct parent is within the designer.
For instance, if you have a Form A, and a UserControl B, in the designer:
A.DesignMode is true when viewed in designer
B.DesignMode is false when viewing A, but true when looking directly at B in the designer.
The solution to this is a special flag to check (sorry for the ugly C++ code):
if(this->DesignMode ||
LicenseManager::UsageMode == LicenseUsageMode::Designtime)
return;
This variable will always show the proper design boolean.
if (this.DesignMode)
{
return; //or call base.OnPaintBackground()
}
The solution of greggorob64 in C#:
if (DesignMode || LicenseManager.UsageMode == LicenseUsageMode.Designtime)
{
return;
}

Categories