Scrollbar in user control - c#

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;
}

Related

Enable all controls on a Panel

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);
}
}

Why do controls delete when copying controls from one panel to the next

I created a template panel to go by when my form loads that holds a record. When adding a new record I have a method that duplicates that template panel and then adds it to my list of panels for each record. Somehow controls are getting deleted from my template panel when I am duplicating it and I have no idea how this is happening. The portion of code doing this is listed below
Panel pn = new Panel()
{
Width = _PNTemp.Width,
Height = _PNTemp.Height,
Left = 0,
Top = 0,
BackColor = _PNTemp.BackColor,
ForeColor = _PNTemp.ForeColor,
AutoScroll = true,
Name = _PNTemp.Name,
Tag = _PrgPanels.Count.ToString()
};
MessageBox.Show(_PNTemp.Controls.Count.ToString());
foreach (Control c in _PNTemp.Controls)
{
pn.Controls.Add(c);
MessageBox.Show(_PNTemp.Controls.Count.ToString());
}
MessageBox.Show(_PNTemp.Controls.Count.ToString());
_PrgPanels.Add(pn);
I put the messagebox.show() in at 3 points to narrow down where it is happening. The first one shows the correct number of controls, the second and third shows a 1/2 the total amount of controls. why is this?
This is because each control can be added to only one parent control. All controls in your template panel are already a child of the template panel. When you try to add these controls to a new panel, the controls will get removed from the template panel.
As per the docs:
A Control can only be assigned to one Control.ControlCollection at a
time. If the Control is already a child of another control it is
removed from that control before it is added to another control.
Which means that you need to create new controls instead of adding those in the template.
An alternative approach is to create a method that returns the template panel. When you need the template panel, just call the method and a new panel will be created:
public static Panel CreateTemplatePanel() {
Panel pn = new Panel();
// set properties, add controls...
return pn;
}
A control can only be on one panel at once. I've added comments inline in your code to help explain whats happening.
Panel pn = new Panel()
{
Width = _PNTemp.Width,
Height = _PNTemp.Height,
Left = 0,
Top = 0,
BackColor = _PNTemp.BackColor,
ForeColor = _PNTemp.ForeColor,
AutoScroll = true,
Name = _PNTemp.Name,
Tag = _PrgPanels.Count.ToString()
};
MessageBox.Show(_PNTemp.Controls.Count.ToString());
//all the controls are still inside _PNTemp
foreach (Control c in _PNTemp.Controls)
{
pn.Controls.Add(c);
MessageBox.Show(_PNTemp.Controls.Count.ToString());
//Each time this runs you remove a control from _PNTemp to pn.
}
//All the controls moved from _PnTemp to pn
MessageBox.Show(_PNTemp.Controls.Count.ToString());
_PrgPanels.Add(pn);

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

Resizing Panel Containing UserControl

I have a UserControl that contains invisible controls, to make them visible, the UserControl resizes.
I need to resize the Panel that contains the UserControl, but I don't know how.
This behavior is handled well by the Panel and Form classes without explicit sizing (and without the layout bugs introduced when the user has a high-DPI monitor or uses the large or extra-large font settings.
1) Create a Form with a docked FlowLayoutPanel.
2) Set the Form and FlowLayoutPanel's AutoSize to true and AutoSizeMode to GrowAndShrink
3) Add your panels and content.
4) Programmatically set the desired panel's Visible property to hidden
hiddenPanel.Visible = false;
5) or true
hiddenPanel.Visible = true;
Put this code in the usercontrol:
Size last = new Size(0, 0);
private void Me_Resize(object sender, System.EventArgs e)
{
if (last != new Size(0, 0)) {
this.Parent.Size = Size.Add(this.Parent.Size, Size.Subtract(this.Size, last));
}
last = this.Size;
}
Will also retain margins (e.g., if the panel is larger than your usercontrol or has other controls beside your usercontrol.)
If you'd like to resize it to a particular size, you can do it on the code behind:
Size panelSize = new Size(500, 500);
usercontrol1.Parent.Size = panelSize;
You could add this code to the usercontrol if that is where you wish to resize from.
To resize the control , call scale of to the control.
// To zoom in controls.
foreach (Control c in MyFlowLayoutPanel.Controls)
{
PictureBox ptc = c as PictureBox;
if (null != ptc)
{
Point pt = new Point(2, 2);
SizeF sf = new SizeF(pt);
c.Scale(sf);
}
}
// To zoom out controls.
foreach (Control c in MyFlowLayoutPanel.Controls)
{
PictureBox ptc = c as PictureBox;
if (null != ptc)
{
SizeF sf = new SizeF(0.5F, 0.5F);
c.Scale(sf);
}
}
I know that this topic is pretty old but I want to add my method, as well...
If you have a Panel containing a UserControl you can easially resize the panel.Controls by firing Form1_Resize event.
private void Form1_Resize(object sender, EventArgs e)
{
foreach (Control control in MasterPanel.Controls)
{
control.Size = MasterPanel.Size;
}
}
Just make sure that you anchor its content properly.

How do I put a panel of buttons into flow layout panel?

I have a panel of labels, buttons and image that I wish to put into a flow layout panel.
As seen in some tutorial, I understand that it is possible to auto align new and additional buttons into a flow layout panel.
what I would like to ask is that is it possible to put a panel WITHIN a flow layout panel and call multiple instances of the same panel to appear within the flow layout panel.
My panel code would be
this.panelNotification.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.panelNotification.Controls.Add(this.button1);
this.panelNotification.Controls.Add(this.lblImage);
this.panelNotification.Controls.Add(this.lblName);
this.panelNotification.Controls.Add(this.lblLinkName);
this.panelNotification.Controls.Add(this.lblLinkLocation);
this.panelNotification.Controls.Add(this.lblLocation);
this.panelNotification.Location = new System.Drawing.Point(3, 3);
this.panelNotification.Name = "panelNotification";
this.panelNotification.Size = new System.Drawing.Size(506, 100);
this.panelNotification.TabIndex = 17;
So is it possible to include the whole panel into a flow layout panel? if yes, how do i do it. thank you.
Yes, you can put a Panel into a FlowLayoutoutPanel.
No, you can't put a control several times into a FlowLayoutoutPanel (in fact you can, but it is only displayed once).
But what you could do is writing some kind of Factory-Method that creates a new Panel with new Buttons/Labels/other Controls etc. every time you call it, and add these new instances to your FlowLayoutpanel. Something like this:
public class Form1
{
private Panel CreateNotificationPanel()
{
var p = new Panel { BackColor = Color.Red };
p.Controls.Add(new Button { Text = "Test" });
return p;
}
private void Form1_Load(System.Object sender, System.EventArgs e)
{
var flp = new FlowLayoutPanel { Dock = DockStyle.Fill };
flp.Controls.Add(CreateNotificationPanel());
flp.Controls.Add(CreateNotificationPanel());
flp.Controls.Add(CreateNotificationPanel());
this.Controls.Add(flp);
}
public Form1() { Load += Form1_Load; }
}
Another (and problably better) approach would be to create a UserControl that contains your Buttons/Labels/etc. instead of using a panel and adding all controls manually. Just create with the Designer and add new instances of the UserControl to the FlowLayoutPanel.

Categories