Enable all controls on a Panel - c#

I want to enable all controls on a Panel. I can loop through the Panel like below.
This doesn't touch all the components though, just the top level ones.
How do I do this? (This is not the answer)
private void LoopThroughAllControls(System.Windows.Forms.Panel panel)
{
for (int i = 0; i < panel.Controls.Count; i++)
{
panel.Controls[i].Enabled = true;
}
}
ToolStrip code that adds ToolStripButton items:
this.toolStripContractor.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.tsbContractor_AddFile,
this.tsbContractor_View,
this.tsbContractor_Delete});

All you have to do is set the Panel's Enabled property to true or false.
From MSDN's page on the Enabled property:
When a container control has its enabled property set to false, all its contained controls are disabled, as well. For example, if the user clicks on any of the controls contained in a disabled GroupBox control, no events are raised.
If, however, you choose to go with a recursive method, here is how to write it:
void SetEnabledAllChildrenOf(Control control, bool enabled)
{
control.Enabled = enabled;
foreach(Control c in control.Controls)
{
SetEnabledAllChildrenOf(c, enabled);
}
}

Related

How to scroll bottom row of TableLayoutPanel into view

At runtime I am adding controls to a control that inherits from TableLayoutPanel. Controls are added one at a time, based on user interaction, not in a loop.
Here's the setup of my control that inherits from the TLP:
this.RowCount = 0;
this.RowStyles.Clear();
this.Dock = DockStyle.Fill;
this.VerticalScroll.Enabled = true;
this.HorizontalScroll.Enabled = false;
this.AutoScroll = true
And I'm adding user-controls to the bottom of the panel like this:
var uc = new FooControl();
this.Controls.Add(uc);
this.SetRow(uc, this.Controls.Count - 1);
this.SetColumn(uc, 0);
I would like to scroll that row/control into view.
How is that done?
To scroll a control into view in a ScrollableControl like TableLayoutPanel, you can use ScrollControlIntoView method. For example:
this.ScrollControlIntoView(uc);
Note: It doesn't select the control.
Also If you call Select method of a control, it will be selected (if selectable) and also its scrollable parent will be scrolled to bring the selected child control into view. For example:
uc.Select();
You can do that by setting the VerticalScroll of the Panel but I think it would be better to use ScrollControlIntoView instead.
private void panel1_ControlAdded(object sender, ControlEventArgs e)
{
panel1.ScrollControlIntoView(e.Control);
}
or
panel.VerticalScroll.Value = panel.VerticalScroll.Maximum

To focus or not to focus

I have a Panel that has AutoScroll = true.
In that Panel is a series of TextBoxes. I should note that the TextBoxes aren't on the panel directly but are nested several levels (about 4-5).
Now, the scrolling with my mouse wheel works only if the panel has focus, naturally. I can use Focus() within mouseEnter event to make sure the panel has focus.
However, the TextBoxes I mentioned earlier rely heavily on focus. Only the user should be able to remove focus from the TextBox by clicking somewhere else.
The TextBoxes are created dynamically and would make for a very messy code to keep an array of them, or any type of reference to check if they have focus. Not to mention that there could be a lot of them.
How do I give the focus to the Panel, but only if none of the TextBoxes is focused?
You don't need to keep an array of the dynamically created Textboxes, you can get the array using:
bool anyTextBoxFocused = false;
foreach (Control x in this.Controls)
{
if (x is TextBox && x.Focused)
{
anyTextBoxFocused = true;
break;
}
}
if (!anyTextBoxFocused)
{
//give focus to your panel
}
Edit
Based on How to get ALL child controls of a Windows Forms form of a specific type (Button/Textbox)?, even nested controls can be obtained using:
public IEnumerable<Control> GetAll(Control control,Type type)
{
var controls = control.Controls.Cast<Control>();
return controls.SelectMany(ctrl => GetAll(ctrl,type))
.Concat(controls)
.Where(c => c.GetType() == type);
}
then use it with:
var c = GetAll(this,typeof(TextBox));

Scrollbar in user control

I have a simple user control like this:
And yes, it has nothing inside, the controls will be dynamically added inside the user control using below on control load event:
List<Control> controlsNeed = getUserControls();
foreach(Control c in controlsNeed)
{
this.Controls.Add(c);
}
The controls loaded correctly, but if there're many controls, there won't be enough space and scroll bars will be needed.
The problem is, the scroll bar isn't added to the control despite setting the below:
Setting AutoScroll to true in the user control
Try setting AutoSize to false and true
What settings / code should be added to add scrollbar to the control?
List<Control> controlsNeed = getUserControls();
int PaddingTop = 10;
foreach (Control c in controlsNeed)
{
this.Controls.Add(c);
c.Location = new Point(0, c.Height + PaddingTop);
}
Or you can inherit the Panle control to your user control that will work like a panel control
public partial class MyControl : Panel
{
}
I think adding AutoScrollMinSize to user control should solve the problem
public MyUserControl()
{
InitializeComponent();
AutoScrollMinSize=new Size(0,1);
AutoScroll = true;
}

why does my usercontrol keep resetting it's visible property to false?

Ok, I have a usercontrol on my page.
On the page, the visible property is set to false.
On the OnPreRender event, I set the visible property to true.
It runs the line of code, but does not actually change anything. (so visible remains at false)
This exact same method works across every other control, and there is nothing special about this control.
Any ideas??
Check for the visible property on any controls containing this control.
Setting Visible=True does not mean that Visible==True, it will still return False if a parent control is False.
Other than that though, you may need to post some examples of your code in order for anyone to help track down what the problem may be.
I faced the same problem and... yes the problem is the parents not be visible. So I made this little peace of code to solve the problem:
public static void ForceVisibleState(Control control, bool visible)
{
if (!visible)
{
control.Visible = false;
}
else
{
// Must set all parents to 'visible = true'
List<Control> parents = new List<Control>();
while (control != null &&
!control.Visible)
{
parents.Insert(0, control);
control = control.Parent;
}
foreach(Control parent in parents)
{
parent.Visible = true;
}
}
}

Getting controls in a winform to disable them

I'm trying to get all controls in a winform disabled at the Load event.
I have a form (MDI) which loads a Login Form. I want to disable the controls behind the Login Form to only let the user enter his username and password, and then if the user is valid re-enable the controls again.
Just show the login form as a modal dialog, i.e., frm.ShowDialog( ).
Or, if you really want to disable each control, use the Form's Controls collection:
void ChangeEnabled( bool enabled )
{
foreach ( Control c in this.Controls )
{
c.Enabled = enabled;
}
}
I suggest doing it this way instead of simply setting the Form's Enabled propery because if you disable the form itself you also disable the tool bar buttons. If that is ok with you then just set the form to disabled:
this.Enabled = false;
However, if you are going to do this you may as well just show the login prompt as a modal dialog :)
Simple Lambda Solution
form.Controls.Cast<Control>()
.ToList()
.ForEach(x=>x.Enabled = false);
Container like Panel control that contains other controls
then I used queue and recursive function get all controls.
for (Control control in GetAllControls(this.Controls))
{
control.Enabled = false;
}
public List<Control> GetAllControls(Control.ControlCollection containerControls, params Control[] excludeControlList)
{
List<Control> controlList = new List<Control>();
Queue<Control.ControlCollection> queue = new Queue<Control.ControlCollection>();
queue.Enqueue(containerControls);
while (queue.Count > 0)
{
Control.ControlCollection controls = queue.Dequeue();
if (controls == null || controls.Count == 0)
continue;
foreach (Control control in controls)
{
if (excludeControlList != null)
{
if (excludeControlList.SingleOrDefault(expControl => (control == expControl)) != null)
continue;
}
controlList.Add(control);
queue.Enqueue(control.Controls);
}
}
return controlList;
}
Just for some fun with linq, because you can.....
What you could do is create a "BatchExecute" extension method for IEnumerable and update all your controls in 1 hit.
public static class BatchExecuteExtension
{
public static void BatchExecute<T>(this IEnumerable<T> list, Action<T> action)
{
foreach (T obj in list)
{
action(obj);
}
}
}
Then in your code....
this.Controls.Cast<Control>().BatchExecute( c => c.enabled = false);
Cool.
I agree that ShowDialog is the way to go, but to answer the original question, you can do this if you want to disable all controls:
foreach (Control c in this.Controls)
{
c.Enabled = false;
}
As Ed said, showing the form as a modal dialog will do what you want. Be sure to check the dialog result returned from ShowDialog in case they cancel it instead of clicking login.
But if you really want to disable all the controls on the form then you should be able to just disable the form itself, or some other parent control like a panel that has all controls in it. That will disable all child controls. This will also allow the child controls to go back to their previous state when the parent control is enabled again.
Trying the ShowDialog show this exception:
Form that is not a top-level form cannot be displayed as a modal dialog box. Remove the form from any parent form before calling showDialog.
What im doing is this:
private void frmControlPanel_Load(object sender, EventArgs e)
{
WindowState = FormWindowState.Maximized;
ShowLogin();
//User = "GutierrezDev"; // Get user name.
//tssObject02.Text = User;
}
private void ShowLogin()
{
Login = new frmLogin
{
MdiParent = this,
Text = "Login",
MaximizeBox = false,
MinimizeBox = false,
FormBorderStyle = FormBorderStyle.FixedDialog,
StartPosition = FormStartPosition.CenterScreen
};
Login.ShowDialog();
}

Categories