Custom anchoring in Windows Forms - c#

I have a custom form that has 4 panels on it edges. I would like to anchor another panel to contain user controls to the visible edges of the form. Once that is done I would then like to anchor an undetermined number of controls to the already anchored panel. I am rather new to this and I do not know that this is the best way to achieve my goal of having a list of objects that resize as the form is resized. The reason I am working at it from this angle is I want the objects to be clickable, and moveable, not just text lines.
My thought is something like this.
----------------------------------------
| Header Panel |
----------------------------------------
|| <--left panel right panel->||
|| [ user control object ]||
|| [ user control object ]||
|| [ user control object ]||
|| [ user control object ]||
----------------------------------------
| Bottom Panel |
----------------------------------------
Currently I am able to draw the panel that holds the user control objects as desired, but it does not resize with the parent, and when I try to anchor it to the parent, it anchors to the wrong place. I have also attempted to anchor the user control objects to the user control panel but they are not resizing at all.
So here is the code for the container panel
//This is called after InitializeComponent(), I would assume the anchor would go
//in here somewhere, but I need the anchor to be offset by the bounds of the
//other panels as listed below.
private static void SetQuestionContainerBounds(SessionReviewForm instance)
{
instance.pnlQuestionContainer.Top = instance.HeaderPanel.Bottom;
instance.pnlQuestionContainer.Left = instance.LeftPanel.Right;
instance.pnlQuestionContainer.Width = instance.RightPanel.Left - instance.pnlQuestionContainer.Left;
instance.pnlQuestionContainer.Height = instance.StatusPanel.Top - instance.pnlQuestionContainer.Top;
}
After I make the form and position the pnlQuestionContainer, I then start making user controls called base question objects, anchor them, and added them to the pnlQuestionContainer
private void DisplayData()
{
// tracks the number of questions, used in placement of objects
int questionCount = 0;
// if the session question is marked for review
// generate a new question object and place it.
foreach (SessionQuestion sq in thisSessionPart.SessionQuestions)
{
if(sq.MarkForReview)
{
BaseQuestionObject bqo = new BaseQuestionObject(sq, parentSession);
BaseQuestionObject.FitAndPlaceObject(pnlQuestionContainer, bqo, questionCount);
bqo.Anchor = (AnchorStyles.Left | AnchorStyles.Right);
pnlQuestionContainer.Controls.Add(bqo);
questionCount++;
}
}
}
A base question object is made up of three parts at the moment. A userControl, a group box, and a label. All of these items are set to autosize with anchor of left, right with the exception of the user control as I cant set that in the properties window, but I think i am setting it in the above method.
The current results are that the container panel is drawn perfectly at first, but it never resizes. The question objects are drawn at the same size that they were made, though this is not the max or the min size.
[EDIT]
The issue I had was the anchor styles were not playing nice with autosize. After turning autosize off and manipulating the anchorStyles I was able to get the desired results.

First, I'm not 100% sure of what you are trying to do but anchoring is much simpler than the way you are trying to achieve it.
Each control has a property called Anchor which is an AnchorStyles enumeration. These values can be Left, Right, Top, Bottom or None and can be bitwised ORed together to allow for multiple anchoring values.
The default 'Anchor' value is Top-Left. If you change the anchoring to Top-Right your controls will remain the same size, but will "float" with the right-side of your application window as it is resized. If you anchor to the Left, Top and Right, your controls will grow and shrink as you resize the width of your window.
I do not believe that you should need any of these panels, unless they are used to logically group controls together. You can experiment with the anchoring by placing a bunch of controls on a form and changing their anchor settings. Run your test form and resize it and see what happens.
Additionally, if you would like to re-arrange the contents of your form as the Window grows and shrinks, the standard MS toolbox has a few controls that you can play around with. Specifically, check out the FlowLayoutPanel and TableLayoutPanel. You can use these controls to fine tune how you want to reposition your child controls on a form or in a section of a form.

Related

Prevent Windows form elements from leaving view when resizing from the bottom?

I have a form set up as shown in the picture below. The form simply contains a SplitContainer with two TreeViews in each of the panels, plus the label above the TreeView.
Here's a picture of the form that has not yet been resized:
Each TreeView is anchored to the Top and Left, and docked to the Bottom.
Each label is anchored to the Top and Left.
The SplitContainer is anchored to the Bottom, Left, and Right.
The above settings allow me to resize the TreeViews equally when the form is resized. However, when I resize the form's height, the labels (and of course the TreeViews as well) are pushed out of the form view, as shown in this picture:
How can I prevent the elements from being pushed past the title bar? Preferrably without the use of a SizeChanged event. I have tried adding padding to the form, as well as trying different docking/anchor modes, but I have been unable to restrict this.
Perform the following steps in order:
Either anchor the SplitContainer to all 4 sides or dock-fill it.
Place the labels on the panels. Make them smaller than the panels, in order to be sure that they really become child controls of the panels (and not of the form). Set their Dock property to Top.
Place the TreeViews on the panel. It is important that this is done after you placed and docked the labels! Same thing here: make them smaller than the panels. Then set their Dock property to Fill.
Note: you can either dock or anchor a control, but not both! The Anchor property is ignored if Dock is something else than None. An anchored edge keeps a constant distance to the side it is anchored to. If an edge is not anchored, the size of the control in this direction will remain unchanged. If two corresponding edges (e.g. left and right) are not anchored, then the control will be centered in this direction.
See: Manage WinForm controls using the Anchor and Dock properties
Set SplitContainer.Dock = DockStyle.Fill; if thats the only thing appearing on the form.

Specify the location of a maximized form?

I have an MDI app, and I have recently added a new control to the MDI container, which covers the client area (the area where the children appear and function). The trouble is, when they try to maximise their forms, it appears behind the sidebar:
Original form for comparison (to see the overlap)
I know that I can restrict the total size of each form that gets maximised, using the Form.MaximumSize property, however I'm not sure how to set the x/y location of the form to sit next to the sidebar.
I could use the side panel as a marker, i.e. x = sidepanel.Width because that will never change, but I don't know how to apply that to a maximised form.
Alternatively, is it possible to give the sidebar the same behaviour as the menu bar? That is - the menu bar is not considered to be in the client area; so when a form is maximised it will not overlap the child form?
Ok, so after some fiddling around, I found the main problem was that since I was adding the control dynamically, control of it was a bit difficult. So instead I did this:
Added a panel (using the forms designer) to the MDI Parent
Set the Dock property to "left"
Added the custom control dynamically to the panel:
SidePanel = new Menu_SidePanel();
SidePanel.Location = new System.Drawing.Point(0, 0);
SidePanel.Anchor = (AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left);
panel1.Controls.Add(SidePanel);
Now, because the panel has been added to, and "docked" on the Parent form, the rest of the child forms, when maximised, use the Side Panel as another boundary.

How to change position of inherited items in an Inherited user control

I have used a user control as a base class (let's call it BaseUC) with 3 labels (in 3 lines) on it (they are set as protected).
And there is another user control that inherits from it (InheritedUC). I have added two more labels in InheritedUC, which are positioned between the base's labels (so there are 5 lines).
Everything is fine is Visiual Studio's design UI view. But when I run the application, labels on BaseUC overlap with the ones in InheritedUC and I can't see the ones on the inherited control.
Any ideas to fix this? Thank you very much
From MSDN: Control.Anchor Property
Use the Anchor property to define how a control is automatically
resized as its parent control is resized. Anchoring a control to its
parent control ensures that the anchored edges remain in the same
position relative to the edges of the parent control when the parent
control is resized.
You can anchor a control to one or more edges of its container. For
example, if you have a Form with a Button whose Anchor property value
is set to Top and Bottom, the Button is stretched to maintain the
anchored distance to the top and bottom edges of the Form as the
Height of the Form is increased.
Set the Anchor property on all labels:
For example:
label1.Anchor = AnchorStyles.Top | AnchorStyles.Left;
If you put your controls in a FlowLayoutPanel and set the following options:
AutoScroll = True
FlowDirection = TopDown
WrapContents = False
Then you should get panel that will grow and shrink as your controls are added or removed.
Source

Resizing contents inside DevExpress Docking Panels

I am attempting to add three panels to a window using a Devexpress Docking manager and dockable panels. Here are the current results:
The three panels are placed and sized how I would like them however their contents will not correctly resize as I resize the window. This first image indicates this by the Picturebox that fails to fill the window. My current attempt to regulate this is: (Panel3 refers to a panel that contains pictureBox1. which in turn is contained by dp3.)
void dp3_SizeChanged(object sender, EventArgs e)
{
panel3.Size = panel3.Parent.Size;
pictureBox1.Width = dp3.Width;
pictureBox1.Height = dp3.Height;
}
The Same is true for the Controls Window. I have controls that do not appear unless the window is grossly oversized.
The controls are contained in 4 seperate panels that are themselves contained in the dockable window.
How do I make things appear the correct size and location whendocking and resizing?
Go throught this DevX article - Designing Resizable Windows Forms in
Visual Studio .NET-2,
that i like most for understanding about layout in Winforms.
You should set the Anchor and Dock properties on the controls in the forms.
The Anchor property controls which edges of a control are "bound" or "tied" to the corresponding edges of its form.
For example, if you set Anchor to Bottom, the distance between the control's bottom edge and the bottom of its parent will not change, so the control will move down as you resize the form.
If you set Anchor to Top | Bottom, the control will resize vertically as you resize the form.
To make a control resize with the form, set the Anchor to all four sides, or set Dock to Fill.
You can set the control's Dock property to Fill. This will cause the control to fill it's parent container.
You may still need to write some code to handle laying out the child controls. You can either do this by handling the Resize event, or by using a container that supports resizing for you (such as FlowLayoutPanel or TableLayoutPanel).
Use your Control's Anchor property. You'll probably need to set it to all sides, Top, Bottom, Left, Right, if you want it to resize according to parent control in all four directions
If you want to Maintain the controls Aspect Ratio on Resize, You'll need to store off the aspect ratio somehow, whether it's something known to you at design time or if you just want to calculate it in the constructor of the form after InitializeComponent(). In your form's Resize event,

Prevent Child Components when Overlapping Panel

I have a WinForms application which has two panels which individually contain a usercontrol component (one in each panel). How ever, because both panels are the same size and in the same location, the top most panel becomes a child of the other panel. I want to be able to hide one panel and then show the other panel:
this.panel1.visibile = false;
this.panel2.visibile = true;
But when I hide panel1, the second panel is hidden as well.
How can I make panel2 a non-child of panel1?
I like to keep things simple because I'm new to C# Programming.
This is a common accident in the designer. Dropping the second panel on top of the first one will make it a child of the first panel. Two basic strategies to fix this:
View + Other Windows + Document Outline. Click the second panel in the list and drag it to the form. You'll need to fix up the Location property by hand by typing its value in the Property window.
Keep the upper left corner of the second panel just a bit to the left or top of the first panel. Put it in the right place in the form's constructor by assigning its Location property after the InitializeComponent() call.
Check this answer for a control that works well at design time and lets you easily flip panels at runtime.
The designer will do this automatically because it assumes that when you drag one control over another, you want to make it a child of that control.
What I usually do to get around this is to create the control in a different place on the form, and then use the properties to manually match the positions of sizes of the two controls.

Categories