Combination of docking and anchoring behaviours in winforms - c#

Today I'm trying to use c# to fit a number of windows controls onto a panel sequentially.
I would like them to dock to the top so that I can then use BringToFront() to stack them up.
HOWEVER I would also like them to be centred. Currently, docking behaviour forces the controls to the left of the screen (however much I resize and change the location property)
I then tried to anchor my controls to the top of the panel instead. This enabled the controls to be centred and also let me resize them but anchoring has no stacking behaviour and each control overwrites the previous one.
I have researched this extensively for hours and have found no answers to this question. Is it possible to use either or both of these properties to stack my controls in the centre of the panel?
My code currently stands as so:
//Docking
userControl.Dock = DockStyle.Top;
userControl.Width = 633;
userControl.Left = (pnlRules.Width - userControl.Width) / 2; //doesn't work
Point location = new Point(((pnlRules.Width - userControl.Width) / 2), 0);
userControl.Location = location; //doesn't work
userControl.BringToFront();
OR
//Anchoring
userControl.Anchor = AnchorStyles.Top;
Point location = new Point(((pnlRules.Width - userControl.Width) / 2), 0);
userControl.Location = location;
userControl.BringToFront(); //doesn't work
My outputs are either stacked controls bound to the left panel edge (docking) or overlapping controls beautifully resized and centred (anchoring)
Thanks :)
Anya
Edit:
This captions my problem quite nicely:
http://www.techrepublic.com/article/manage-winform-controls-using-the-anchor-and-dock-properties/
This explains that using docking, the controls can be stacked next to each other. I would just like the docked, stacked controls to not be bound to the left edge of the panel.

There is no way to use a combination of docking and anchoring. A TableLayoutPanel may have worked here but I was tied to a simple Panel.
The fix was to use padding to force the control to centre:
userControl.Dock = DockStyle.Top;
pnlParent.Padding = new Padding((pnlParent.Width - userControl.Width) / 2, 0, 0, 0);
userControl.BringToFront();

Related

How to make a Windows Form responsive [duplicate]

I have read several stack overflow questions without finding a good working solution to my problem. How can I resize my controls whenever the form is resized? I would like them to get larger or smaller when the form becomes larger or smaller.
In visual basic this was quite easy to do with the form.Zoom property (which did't really require resizing controls of course, but solved what I needed). Unfortunately this is not available in C# winforms.
Here is some other things I have tried without luck:
private void formMain_Resize(object sender, EventArgs e)
{/*
double scale;
this.scaleWidth = (float)this.Width / (float)this.origWidth;
this.scaleHeight = (float)this.Height / (float)this.origHeight;
if (this.scaleHeight > this.scaleWidth)
{
scale = this.scaleHeight;
}
else
{
scale = this.scaleWidth;
}
foreach (Control control in this.Controls)
{
control.Height = (int)(control.Height * this.scaleHeight);
control.Width = (int)(control.Width * this.scaleWidth);
this.Refresh();
// control.Font = new Font("Verdana", control.Font.SizeInPoints * heightRatio * widthRatio);
}
///////This scaling didnt work for me either
//this.Scale(new SizeF(this.scaleWidth, this.scaleHeight));
//this.Refresh();
*/
}
If I overlooked an actualy working sample of code on another stack overflow question I would love to see it, but the ones I found were similar to those above which are not working.
Perhaps I was misusing it and someone could post sample code to show for those of us who keep asking this question how to go about solving the problem.
Also, I have tried using some of the anchor/docking tools thinking they would automatically allow it but it didn't.
The best option is to use a TableLayoutPanel. Put TableLayoutPanel on the form, set the Dock property to Fill, create required rows and columns and put the controls inside the cells. Of course you need to set Dock/Anchor on the controls inside the cells, so they respond to changes to the cell size. In some situations you may need to put a Panel into a cell and drop the controls inside it, because every cell can only contain a single control. You may also need to set RowSpan/ColumnSpan on the controls.
By using a TableLayoutPanel, you have complete control over how your cotrols should be arranged. You can set absolute or percentage size for rows and columns.
Use Anchor of the control. There's an option on anchoring the top, bottom, left and right. And you're good to go.
I found an alternative solution that is working well for me, appreciate any negative or positive comments on the solution.
Using several Split Containers and Split Containers inside of Split Containers in different regions I am able to section off the primary pieces of the layout, and within there utilizing Docking and Anchoring I am able to accomplish exactly what I wanted to do - it works beautifully.
I would point out I am aware that some folks online mention split containers use lots of resources.
If your controls are in a group box, be sure to set the group boxes properties to resize. Controls inside the box are controlled by the box. The box size (unless it is inside another box) is controlled by the form.
What you are trying to do in your code is to change the sizes of the controls which isn't so good approach. Generally, the size of the Buttons and TextBoxes shouldn't be changed when you re-size your form, but they often need to move (change location). Some controls do need to change size according to the re-sized form and but in most cases only one dimension. The central controls that are used for working area (if you are developing the tool for drawing for instance) should change sizes of both dimensions. All this you can accomplish by properly setting Dock and/or Anchor properties of the controls.
textBox1.Dock = DockStyle.Bottom;
textBox1.Anchor = AnchorStyles.Bottom & AnchorStyles.Left;
All these are also easily set in the Properties panel when using designer.
But if that isn't enough for you, in rare cases, you will most definitely want to only change the location of the control:
textBox1.Location = new Point(newX, newY);

How to place a label or a button exactly in the middle of the Form?

I can't find tools or properties to place a label or a button exactly in the middle of the Form. For example, on the X axis. VS 2015.
Design time :
In my VisualStudio2010 I have these 2 buttons to center horizontally and vertically:
Its located in the toolbar "Layout". If it isn't, you can add them by clicking the small button to the right. It is also in the Format menu.
To keep centered at Runtime: Turn off all anchoring.
Note:This will keep the control at its relative position as long as it doesn't change it Size. If it does, like autosize Labels are prone to, you will have to code the Resize event. Examples are here
For controls that may change in size, you need to catch the Resize event.
In my case I have a Panel, representing a page, inside another Panel which is the workspace. The workspace is set to autoscroll. In this scenario, it's important that the control is only centered when smaller than the container.
Whenever the form changes size or when I change the content, I call this function:
private void resetPagePos()
{
int wWS = pnlWorkspace.Width;
int hWS = pnlWorkspace.Height;
int wPage = pnlPage.Width;
int hPage = pnlPage.Height;
pnlPage.Location = new Point(Math.Max(0, (wWS - wPage) / 2), pnlPage.Top = Math.Max(0, (hWS - hPage) / 2));
}
The use of Math.Max(0, ...) makes sure that if the item doesn't fit, and the scrollbars are activates, then our page scrolls correctly. If the Left or Top are set to a negative number, you would get unwanted side-effects.

SplitContainer Panel Resize Issue

The General Problem
The application is C# WinForms .Net 4.0.
I have a SplitContainer that takes up most of the form, it is set to Anchor in all directions so it re-sizes along with the form. The left panel (Panel1) has a simple menu, no problems here. The right panel (Panel2) is more complex and contains a number of nested tab controls (with lots of controls) - it is painfully complex, but it's not changing.
The problem is that re-sizing the form doesn't work so well. In fact, if you resize by dragging the edges slowly then it works ok, but drag quickly or use the "restore" button (top-right of form) then the issue occurs.
My Control Hierarchy
The following is a simple example of my control hierarchy, its definitely a cut down version but does highlight the nested tab control which may help with replication:
Form
Split Container (anchor: top, left, bottom, right)
SC Panel1 (min width: 300)
TreeViewControl (forget what it is called)
SC Panel2
Panel (anchor: top, left, bottom, right)
Tab Control (anchor: top, left, bottom, right)
Tab Control w/ lots of pages that overflow screen and require the navigation buttons to show in top right corner (anchor: top, left, bottom, right)
Debug Details
After some debugging it appears that it is in fact Panel2 (a child of the split container) that doesn't resize properly, and the actual SplitContainer itself resizes fine.
Here are the debug values that show this...
Full width form, before resize:
splitContainerMain.Width: 1479
splitContainerMain.Panel2.Width: 1206
panelCenter.Width: 1203
tabControlMain.Width: 1215
All as expected, splitContainerMain.Panel2.Width is smaller than splitContainerMain.Width.
After resize where the issue occurs:
splitContainerMain.Width: 815
splitContainerMain.Panel2.Width: 1206
panelCenter.Width: 1203
tabControlMain.Width: 1215
As can be seen, the splitContainerMain.Width has resized as desired, but the splitContainerMain.Panel2.Width and subsequently its children have not.
NOTE: Please remember, the width updates correctly if I manually resize the form slowly - this is not a problem with me not correctly setting any anchors.
My Efforts So Far
What I have tried to do is use various Form resize events and try to set the widths manually, but to no avail. I think what I would like to try is to set the Panel2.Width value from within an event of some sort.
What I Am Looking For
Is there anyway to force splitContainerMain.Panel2.Width to resize correctly when the splitContainerMain size changes?
Alternatively, how can I calculate what the Panel2.Width should be? And how can I set that value from the Form.Resize event? (or another event?)
Though the question is about 6 years old, I opted to answer this because I was in the same situation as the opening post. Unfortunately, the orientation was not specified. So, my answer would address the ones with Horizontal orientation.
Please translate to C# as this code is in VB.
Private Sub splitContainerMain_Resize(sender As Object, e As EventArgs) Handles splitContainerMain.Resize
'/* This is a work around about panels being left out when SplitContainer is resized */
Dim pnl1Height As Single = splitContainerMain.SplitterDistance '/* Get upper panel height */
Dim pnl2Height As Single = splitContainerMain.Height - splitContainerMain.SplitterDistance '/* Get lower panel height */
splitContainerMain.Panel1.SetBounds(0, 0, splitContainerMain.Width, pnl1Height) '/* Set Upper panel bounds */
'/* Set lower panel bounds, with a top of upper panel height plus splitter width */
splitContainerMain.Panel2.SetBounds(0, pnl1Height + splitContainerMain.SplitterWidth, splitContainerMain.Width, pnl2Height)
End Sub
From what I see u should set anchor to none for controls that are creating problem including splitcontainer pannels.
Also I would suggest to use dock fill property to best use the splitcontainers.
If need further help please provide designer file so can have a better look.
So on each Change event you are creating a new thread, that thread will then wait 100 ms and then do the recize??? thats stupid. You can have a thread created at the constructor, then calling Start() on your thread which could have the following:
private void resizeMe()
{
this.BeginInvoke((Action)() => {
splitContainer.Height = tableBorder.Height;
splitContainer.Width = tableBorder.Width;
}
}
Exactly the same problem, below code worked for me:
Surround splitContainer in a panel "tableBorder"
On tableBorder
Dock = DockStyle.Fill;
On split Container, (no anchoring)
Dock = DockStyle.None;
On tableBorder SizeChanged event
private void tableBorder_SizeChanged(object sender, EventArgs e)
{
new Thread(() => { resizeMe(); }).Start();
}
private void resizeMe()
{
Thread.Sleep(100);
this.BeginInvoke((Action)(() => {
doIt();
}));
}
private void doIt()
{
splitContainer.Height = tableBorder.Height;
splitContainer.Width = tableBorder.Width;
}
There is a small lag, but works

Resize Controls with Form Resize

I have read several stack overflow questions without finding a good working solution to my problem. How can I resize my controls whenever the form is resized? I would like them to get larger or smaller when the form becomes larger or smaller.
In visual basic this was quite easy to do with the form.Zoom property (which did't really require resizing controls of course, but solved what I needed). Unfortunately this is not available in C# winforms.
Here is some other things I have tried without luck:
private void formMain_Resize(object sender, EventArgs e)
{/*
double scale;
this.scaleWidth = (float)this.Width / (float)this.origWidth;
this.scaleHeight = (float)this.Height / (float)this.origHeight;
if (this.scaleHeight > this.scaleWidth)
{
scale = this.scaleHeight;
}
else
{
scale = this.scaleWidth;
}
foreach (Control control in this.Controls)
{
control.Height = (int)(control.Height * this.scaleHeight);
control.Width = (int)(control.Width * this.scaleWidth);
this.Refresh();
// control.Font = new Font("Verdana", control.Font.SizeInPoints * heightRatio * widthRatio);
}
///////This scaling didnt work for me either
//this.Scale(new SizeF(this.scaleWidth, this.scaleHeight));
//this.Refresh();
*/
}
If I overlooked an actualy working sample of code on another stack overflow question I would love to see it, but the ones I found were similar to those above which are not working.
Perhaps I was misusing it and someone could post sample code to show for those of us who keep asking this question how to go about solving the problem.
Also, I have tried using some of the anchor/docking tools thinking they would automatically allow it but it didn't.
The best option is to use a TableLayoutPanel. Put TableLayoutPanel on the form, set the Dock property to Fill, create required rows and columns and put the controls inside the cells. Of course you need to set Dock/Anchor on the controls inside the cells, so they respond to changes to the cell size. In some situations you may need to put a Panel into a cell and drop the controls inside it, because every cell can only contain a single control. You may also need to set RowSpan/ColumnSpan on the controls.
By using a TableLayoutPanel, you have complete control over how your cotrols should be arranged. You can set absolute or percentage size for rows and columns.
Use Anchor of the control. There's an option on anchoring the top, bottom, left and right. And you're good to go.
I found an alternative solution that is working well for me, appreciate any negative or positive comments on the solution.
Using several Split Containers and Split Containers inside of Split Containers in different regions I am able to section off the primary pieces of the layout, and within there utilizing Docking and Anchoring I am able to accomplish exactly what I wanted to do - it works beautifully.
I would point out I am aware that some folks online mention split containers use lots of resources.
If your controls are in a group box, be sure to set the group boxes properties to resize. Controls inside the box are controlled by the box. The box size (unless it is inside another box) is controlled by the form.
What you are trying to do in your code is to change the sizes of the controls which isn't so good approach. Generally, the size of the Buttons and TextBoxes shouldn't be changed when you re-size your form, but they often need to move (change location). Some controls do need to change size according to the re-sized form and but in most cases only one dimension. The central controls that are used for working area (if you are developing the tool for drawing for instance) should change sizes of both dimensions. All this you can accomplish by properly setting Dock and/or Anchor properties of the controls.
textBox1.Dock = DockStyle.Bottom;
textBox1.Anchor = AnchorStyles.Bottom & AnchorStyles.Left;
All these are also easily set in the Properties panel when using designer.
But if that isn't enough for you, in rare cases, you will most definitely want to only change the location of the control:
textBox1.Location = new Point(newX, newY);

Panel with fixed size

I have a homework, where I need to create a winforms game using C#. I have the following components:
Panel subclass with custom paint event
Panel with default windows UI elements.
I want them to arrange like this:
Because I draw on the center panel manually, I want to set it's Width, and Height fixed, so the Form subclass, what will contain it, would show the whole panel.
I tried setting the size manually in the panel subclass:
Width = someFixedWidth;
Height = someFixedHeight;
Then adding it to the containing Form:
GamePanel panel = new GamePanel(...);
panel.Dock = DockStyle.Center;
this.AutoSize = true;
this.AutoSizeMode = AutoSizeMode.GrowAndShrink;
this.Controlls.Add(panel);
Using this, I thought, that the form will respect the size of the Panel, but it just shrinks the window to so small, that nothing is visible, only the title.
So my question is, how would I be able to set the size of the GamePanel manually, and then dock it in the center of the form, so that the Form will respect the size I set, and doesn't makes it smaller/bigger?
The Dock property is used to define the behavior of the component during resizing Container (Form) The way you did the screen is not centralized but is resized according to the screen changes, the ideal is to use a method to reposition the control and set its size. See this:
SuspendLayout();
Width = someFixedWidth;
Height = someFixedHeight;
panel.Size = new Size(panelWidth, panelHeight);
panel.Location = new Point( ClientSize.Width / 2 - panelWidth / 2, ClientSize.Height / 2 - panelHeight / 2);
panel.Anchor = AnchorStyles.None;
panel.Dock = DockStyle.None;
ResumeLayout();
In my case, I edited minimum height/width of the panel and it worked.
I tried to edit the code which related to design but it was not recommended to rewrite auto-generated code.
Thank you.

Categories

Resources