How do I center content in a Panel? - c#

I have a panel, inside which I am trying to center the controls. But apparently, panels don't like padding when they are docked to the edge of a control. Here is the current code for my panel:
buttonPanel = new Panel();
buttonPanel.Width = 300;
buttonPanel.Height = 50;
buttonPanel.Dock = DockStyle.Bottom;
buttonPanel.Padding = new Padding((this.ClientSize.Width - buttonPanel.Width) / 2, 0,
(this.ClientSize.Width - buttonPanel.Width) / 2, 0);
buttonPanel.BackColor = Color.Transparent;
this.Controls.Add(buttonPanel);
I have a single button placed inside the panel. What I would expect with the above code, is that the control is placed nicely to the left of a 300 wide "rectangle" centered in the panel. But the button is placed on the very left, as if the padding is ignored:
How can I center a collection of buttons to the center of my form?

Design Time Approach
At design time, put your button in your container and select your button. Then, use Center Horizontally and Center Vertically from Layout toolbar to put your button in center of panel. After, go to your buttons properties and remove every anchor from Anchor property.
Coding Approach
Panel panel = new Panel();
panel.Size = new Size(300, 100);
panel.Dock = DockStyle.Bottom;
Button button = new Button();
button.Size = new Size(70, 25);
button.Location = new Point((panel.Width - button.Width) / 2, (panel.Height - button.Height) / 2);
button.Anchor = AnchorStyles.None;
panel.Controls.Add(button);
this.Controls.Add(panel);

You have to align the button inside the panel by setting the button's position not the panel's padding:
button1.Left = (int)(panel1.Width * 0.5f - button1.Width * 0.5f);
button1.Top = (int)(panel1.Height * 0.5f - button1.Height * 0.5f);
or
button1.Location = new Point()
{
X = panel1.Width / 2 - button1.Width / 2,
Y = panel1.Height / 2 - button1.Height / 2
};
the result is the same.
If you override the OnResize method the button will stay centered also when you change the size of the form:
protected override void OnResize(EventArgs e)
{
button1.Location = new Point()
{
X = panel1.Width / 2 - button1.Width / 2,
Y = panel1.Height / 2 - button1.Height / 2
};
base.OnResize(e);
}

Related

How to make a vertical scrollview Xamarin

I am trying to make a vertical scrollview in Xamarin(for iOS). The scroll view scrolls up and down vertically how it is supposed to but when I populate it with buttons they are added horizontally. I am new to Xamarin and the only example they give is a horizontal scrollview it seems. Thanks in advance here is my code :
nfloat h = 50.0f;
nfloat w = 150.0f;
nfloat padding = 10.0f;
scrollView = new UIScrollView
{
Frame = new CGRect(0, 100, View.Frame.Width, View.Frame.Height),
ContentSize = new CGSize(View.Frame.Width,View.Frame.Height*3),
BackgroundColor = UIColor.White,
AutoresizingMask = UIViewAutoresizing.FlexibleHeight
};
//This is in a separate area and there are a few more of these blocks of code
var button = UIButton.FromType(UIButtonType.RoundedRect);
button.SetTitle(ln, UIControlState.Normal);
button.Frame = new CGRect(padding * (i + 1) + (i * w), padding, w, h);
button.TouchUpInside += Button2TouchUpInside;
scrollView.AddSubview(button);
buttons.Add(button);
//then finally
View.AddSubview(scrollView);

Windows Forms C# draw whole scrollable panel

I have a problem with my scrollable panel in Windows Forms C#.
My Situation
I have a Form with a tabControl.
In 1 of the tabs i have a panel that fills the whole tab and is scrollable.
In runtime i fill this panel with about 60 other panels and 6 pictures in each of the added panels. This leads to 1 big panel that i can scroll down.
My Problem
Now drawing 1 of these sub panels takes about 0.2 seconds on my bad pc which is fine and reaosnable but i have the problem that it is only drawing the things that are currently visible in the main panel.
Even if i let the main panel load for 1 minute he still only draws the first couple of sub panels and if i scroll down he has to draw the rest.
If i scroll up again everything is smoot, so it looks like it is storing everything that was drawn once.
I would like abehaviour where he basically draws the whole main panel in the beginning and afterwards the scrolling is smooth.
PS: I am not sure if "drawing" is the right word for what the form is doing.
PPS: I know that this code is not perfect, but I am not complaining about performance issues but I just want to understand how this loading works
Some code:
private void Form1_Load(object sender, EventArgs e) {
pnEverything.Controls.Clear();
int yPosition = 20;
for (int i = 1; i <= 48; i++) {
Panel panel = new Panel();
Label label = new Label();
if (i % 2 != 0) {
panel.Location = new Point(10, yPosition);
}
else {
panel.Location = new Point(this.Size.Width / 2 + 10, yPosition);
yPosition += this.Size.Width / 10;
}
panel.Size = new Size(this.Size.Width / 2 - 80, ((this.Size.Width / 2 - 80) - 90) / 6 + 40);
panel.Tag = i;
panel.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
label.AutoSize = true;
label.Font = new Font("Microsoft Sans Serif", 15.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
label.ForeColor = Color.Black;
label.Name = "lbLade" + i;
label.Location = new Point(panel.Width / 2 - label.Size.Width / 2, panel.Size.Height - 30);
label.Text = i.ToString();
panel.Controls.Add(label);
int xPosition = 30;
for (int j = 1; j <= 6; j++) {
MyPictureBox pb = new MyPictureBox();
pb.Location = new Point(xPosition, 10);
pb.Margin = new Padding(2);
pb.Name = "pbLade" + i + "Nummer" + j;
pb.Size = new Size((panel.Size.Width - 90) / 6, (panel.Size.Width - 90) / 6);
pb.SizeMode = PictureBoxSizeMode.StretchImage;
pb.Cursor = System.Windows.Forms.Cursors.Hand;
pb.Position.Lade = i;
pb.Position.Nummer = j;
xPosition += pb.Size.Width + 10;
pb.ImageLocation = #"Bilder\plus.png";
pb.Click += new EventHandler(pbAddCar_Click);
panel.Controls.Add(pb);
}
pnEverything.Controls.Add(panel);
}
}
After Activate the form, Load one Panel and remaining you can load in the Background worker and Invoke.

Panel autoscroll when value out of the boundaries

I'm having a problem with panels.
I'm adding points to a panel with this code:
void panelDraw_Paint(object sender, PaintEventArgs e)
{
if (this.MeasuredValue == null)
return;
var g = e.Graphics;
int x = 0;
foreach (value m in this.MeasuredValue )
{
double percentage = m.MeasuredValue [(int)this.MeetType].GetValueOrDefault() / this.MaxValue * (double)100;
double y = this.Height / (double)100;
double pixels = y * percentage;
g.DrawRectangle(Pens.Green, x++, this.Height - (int)pixels, 1, 1);
g.DrawLine(Pens.GhostWhite, 0, this.Height / 4, panelDraw.Width, this.Height / 4);
g.DrawLine(Pens.GhostWhite, 0, this.Height / 2, panelDraw.Width, this.Height / 2);
g.DrawLine(Pens.GhostWhite, 0, (this.Height / 4) * 3, panelDraw.Width, (this.Height / 4) * 3);
if (x > panelDraw.Width)
{
panelDraw.AutoScroll = true;
}
}
}
The dimension of my panel is 230;218
I'ld like to see my points when x goes out of the boundaries (bigger then 230) but somehow autoscroll doesn't work ..
I did also set AutoScroll on true in the panel properties from the beginning, but that also doesn't work.
This is what I get, when x is bigger than my panel width:
How can I see my points when they are out of the boundaries of the panel?
The reason why the panel does not show any scroll bars is that it does not know anything of its content. Even if it would scroll, the view would not change because you don't take the scroll position into account when painting the content.
Instead of painting directly to the panel, you should add another control with the appropriate size to it and paint on this control. This will give the panel the necessary scroll hints and you don't have to handle scrolling manually.

How can I make a button take up its entire containing form?

I've made a floating button. I want it to take up the whole of the it's containing form but the below code has a margin between the right of the button and the right of the form.
public FloatButton()
{
InitializeComponents();
int width = (int)((double)Screen.PrimaryScreen.Bounds.Width / 20);
int height = (int)((double)Screen.PrimaryScreen.Bounds.Height / 20);
this.WindowState = FormWindowState.Normal;
FormBorderStyle = FormBorderStyle.None;
int x_pos = Screen.PrimaryScreen.Bounds.Width - width;
int y_pos = Screen.PrimaryScreen.Bounds.Height / 2 - height / 2;
this.Location = new Point(x_pos,y_pos);
this.Height = height;
this.Width = width;
this.button.Width = width;
this.button.Height = height;
}
EDIT: It's about 40 pixels and it doesn't change if I make the button text longer (the text wraps)
Does docking work for you?
this.button.Dock = System.Windows.Forms.DockStyle.Fill;
Just setting Dock to Fill should make the button fill up its parent's entire area.

Keeping a PictureBox centered inside a container

I am designing a simple picture viewer with ability to do some basic image processing. At the moment I have the problem of keeping the PictureBox centered inside a TabPage all the time as well as keeping the picturebox width and size same as the picture its showing. So far I had no success.
I have the following code that I call in form constructor to position it in center. it works the first time to center the picturebox:
private void SetPictureBoxOriginalSizeAndLocation(bool makeImageNull = false, DockStyle dockStyle = DockStyle.None)
{
if (makeImageNull) picBoxView.Image = null;
picBoxView.Dock = dockStyle;
var xPoint = tabImageView.Location.X + ((splitContainer.Panel2.Width / 2) / 2);
var yPoint = tabImageView.Location.Y;
var width = tabImageView.Width / 2;
var height = (tabImageView.Height / 2) - toolStripImageView.Height;
if (picBoxView.Image == null) return;
//Resize image according to width
picBoxView.Image = ImageMethods.ResizeImage(picBoxView.Image.Tag.ToString(), width, height, false);
picBoxView.Location = new Point(xPoint, yPoint);
picBoxView.Width = width;
picBoxView.Height = height;
}
But it does not resize the picturebox to its image (you can see the black part that is back color for the picturebox control):
The problem is getting worse as soon as I resize the form, the picturebox position will goes to top:
I call the code above in form's resize event as well, no idea why it works when application starts. Would be nice if someone can tell me what properties I should take care of to achieve a nicely centered picturebox which always is as big as its image.
It's pretty easy if you just set the Anchor style to none:
picBoxView = new PictureBox();
picBoxView.SizeMode = PictureBoxSizeMode.AutoSize;
picBoxView.Anchor = AnchorStyles.None;
tabImageView.Controls.Add(picBoxView);
CenterPictureBox(picBoxView, myImage);
Then just center the PictureBox initially whenever you change the image of the PictureBox:
private void CenterPictureBox(PictureBox picBox, Bitmap picImage) {
picBox.Image = picImage;
picBox.Location = new Point((picBox.Parent.ClientSize.Width / 2) - (picImage.Width / 2),
(picBox.Parent.ClientSize.Height / 2) - (picImage.Height / 2));
picBox.Refresh();
}
Having the Anchor = None will center the PictureBox control for you whenever the parent container gets resized because it "isn't" anchored to the default Left and Top locations.
Givien a Form with TabControl, which has Dock set to Fill, below will keep your PictureBox in the centre. It also sets PictureBox size to Bitmap size:
public partial class Form1 : Form
{
Bitmap b = new Bitmap(320, 200);
public Form1()
{
InitializeComponent();
CenterTheBox();
}
private void Form1_Resize(object sender, EventArgs e)
{
CenterTheBox();
}
void CenterTheBox()
{
pictureBox1.Size = b.Size;
var left = (tabPage1.ClientRectangle.Width - pictureBox1.ClientRectangle.Width) / 2;
var top = (tabPage1.ClientRectangle.Height - pictureBox1.ClientRectangle.Height) / 2;
pictureBox1.Location = new Point(tabPage1.ClientRectangle.Location.X + left, tabPage1.ClientRectangle.Location.Y + top);
}
}
I believe your problem lies here
var xPoint = tabImageView.Location.X + ((splitContainer.Panel2.Width / 2) / 2);
var yPoint = tabImageView.Location.Y;
var width = tabImageView.Width / 2;
var height = (tabImageView.Height / 2) - toolStripImageView.Height;
ypoint is alwways set to tabImageView Y, althought it should be set to
tabImageView.Location.Y + (tabImageView.Size.Height - picBoxView.Size.Height)/2
should be almost the same with xPoint
tabImageView.Location.X + (tabImageView.Size.Width - picBoxView.Size.Width)/2
and
width = picBoxView.Image.Width;
height = picBoxView.Image.Height;

Categories