I'm trying to create an autosizing button grid using a TableLayoutPanel. When I add columns at runtime with the following code they are not being sized evenly:
tableLayoutPanel.ColumnCount += 1;
for (var i = 0; i < tableLayoutPanel.RowCount; i++) {
var button = new Button {
Margin = Padding.Empty,
Padding = Padding.Empty,
Dock = DockStyle.Fill
}
tableLayoutPanel.Controls.Add(button);
}
The initial form with 1 column:
Adding a 2nd column:
Adding a 3rd column:
Is there a way to make the columns autosize evenly without manually calculating the dimensions?
It's necessary to explicitly reset the column styles:
private void RecalculateColumnStyles()
{
var cols = tableLayoutPanel.ColumnCount;
var pct = (float) 100 / cols;
tableLayoutPanel.SuspendLayout();
tableLayoutPanel.ColumnStyles.Clear();
for (var i = 0; i < cols; i++) {
tableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, pct));
}
tableLayoutPanel.ResumeLayout();
}
Related
I want to disable rows autoscaling of TableLayoutPanel so that it would fit, for example, 4 columns on width and 3 rows on height and autoscrolling also would work. What should I change?
Code:
public UserControl()
{
InitializeComponent();
tableLayoutPanel1.ColumnStyles.Clear();
tableLayoutPanel1.RowStyles.Clear();
foreach (Picture picture in Program.gallery)
addImage(picture);
for (int i=0;i<tableLayoutPanel1.ColumnCount;i++)
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100f/4));
for (int i = 0; i < 99999; i++)
tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100f/3));
}
TableLayoutPanel has:
AutoScroll=true;
AutoSize=false;
ColumnCount=4;
RowCount=3;
Dock=true;
GrowStyle=AddRows;
Percent size type is broken.
Scrollbar of TableLayoutPanel is also glitchy and is not shrink. Here
I used these properites for table:
AutoScroll=false;
AutoSize=true;
ColumnCount=4;
RowCount=0;
Dock=Top;
GrowStyle=AddRows;
and external control property:
AutoScroll=true;
Code for checking rows count and disabling unused:
private int cellsCount=0;
private const int rows = 3;
private int CellsCount {
get => cellsCount;
set {
cellsCount = value;
int expectedRows = (cellsCount - 1 + tableLayoutPanel1.ColumnCount) / tableLayoutPanel1.ColumnCount;
while (expectedRows > tableLayoutPanel1.RowCount)
{
tableLayoutPanel1.RowCount++;
tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, Height/rows));
}
while (expectedRows < tableLayoutPanel1.RowCount) {
tableLayoutPanel1.RowCount--;
tableLayoutPanel1.RowStyles.RemoveAt(0);
}
}
}
And resize listener to set true dimensions of rows:
private void tableLayoutPanel1_Resize(object sender, EventArgs e)
{
foreach (RowStyle row in tableLayoutPanel1.RowStyles)
row.Height = Height / rows;
}
I am adding 8 panels to a "flowLayoutPanel1". It works fine.
The problem is that it comes 4 panels on the first"row" and then 4 panels on next "row".
The thing is that I have made the size of the "flowLayoutPanel1" to visually show 3 panels on each "row", - so in this case, half of the 4th panel on each row are not seen.
But if I add them in the designer manually, it do come 3 panels on each "row" which I want.
I wonder why this is happening when I add them dynamically with this code?
flowLayoutPanel1.Controls.Clear(); int count = 0;
for (int n = 0; n < 4; n++)
{
for (int i = 0; i < latestImageLIST.Count; i++)
{
//Now add all images as panels
String imagefile = latestImageLIST[i];
if (File.Exists(imagefile))
{
Panel panel = new Panel(); count++;
panel.Name = "thepanel" + count;
panel.Size = new Size(284, 160);
panel.Margin = new Padding(3);
Image image = Image.FromFile(imagefile);
panel.BackgroundImage = image;
panel.BackgroundImageLayout = ImageLayout.Stretch;
panel.Tag = "thepanel" + count;
panel.Click += new System.EventHandler(this.panel216_Click);
flowLayoutPanel1.Controls.Add(panel);
}
}
}
I recommend using TableLayoutPanel, which is an alternative to FlowLayoutPanel. You can first determine the row and column based on the number of images you need to load, then dynamically create a Panel through a loop and add it to the specified row and column.
public void AddImages(int row, int col)
{
TableLayoutPanel tlp = new TableLayoutPanel();
int prow = 100 / row, pcol = 100 / col;
for(var i=0;i<row;i++)
{
tlp.RowStyles.Add(new RowStyle(SizeType.Percent, prow));
}
for(var i=0;i<col;i++)
{
tlp.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, pcol));
}
//modify the add logic according to your requirement.
tlp.Controls.Add(new Panel() { Dock = DockStyle.Fill }, 1, 1);
//todo...
this.Controls.Add(tlp);
}
I have a TableLayoutPanel, ug_degrees, with 3 columns and 1 row. Each cell gets dynamically populated with another TableLayoutPanel, degreePanel, containing 1 label and 1 textbox.
I need to get my layout to look something like this:
Right now my layout looks like this:
I'm at a loss for why I have those giant gaps between the cells, and why the row will not expand to fill its contents (a label & a textbox). I have tried to set the whole TableLayoutPanel's autosize property to true, but the columns get resized, even if I set only the rows' sizetype to autosize as well.
The properties behind the table shown are default. All non-default properties are customized in C# below.
// Dynamically load undergraduate degrees
int row = 0;
for (int i = 0; i < degrees.undergraduate.Count; i++) {
// Create and populate panel for each degree
TableLayoutPanel degreePanel = new TableLayoutPanel();
degreePanel.ColumnCount = 1;
degreePanel.RowCount = 2;
degreePanel.AutoSize = true;
foreach (RowStyle style in degreePanel.RowStyles) {
style.SizeType = SizeType.AutoSize;
}
degreePanel.BorderStyle = BorderStyle.FixedSingle;
//degreePanel.Margin = new Padding(0);
Label degTitle = new Label();
degTitle.Text = degrees.undergraduate[i].title;
degTitle.Dock = DockStyle.Fill;
TextBox degDesc = new TextBox();
degDesc.ReadOnly = true;
degDesc.Multiline = true;
degDesc.Dock = DockStyle.Fill;
degDesc.Text = degrees.undergraduate[i].description;
SizeF size = degDesc.CreateGraphics()
.MeasureString(degDesc.Text,
degDesc.Font,
degDesc.Width,
new StringFormat(0));
degDesc.Height = (int)size.Height;
degreePanel.Controls.Add(degTitle, 0, 0);
degreePanel.Controls.Add(degDesc, 0, 1);
ug_degrees.Controls.Add(degreePanel, i, row);
// Resize rows and columns (only after adding controls)
foreach (RowStyle style in ug_degrees.RowStyles) {
style.SizeType = SizeType.AutoSize;
}
// Jump to next row if current row is full
if ((i+1) % 3 == 0) {
row++;
}
Add degreePanel.Dock = DockStyle.Fill
How to get picture box image at right side in TableLayoutPanel in c#? At present i am getting two images besides but i don't need. i need only one image to their at extreme right side and i need to remove space between two rows
for (int i = 0, r = 0; i < dt.Rows.Count; i++, r++)
{
PictureBox pb = new PictureBox();
pb.ImageLocation = ../imagesDT/answered.gif
tableLayoutPanel1.Controls.Add(pb);
}
Below is my attached image i am getting issue as described above.
You need to set the Column and the Row those PictureBoxes shall sit in:
for (int i = 0, r = 0; i < dt.Rows.Count; i++, r++)
{
int maxCol = tableLayoutPanel1.ColumnCount - 1;
PictureBox pb = new PictureBox();
pb.ImageLocation = ../imagesDT/answered.gif
tableLayoutPanel1.Controls.Add(pb);
tableLayoutPanel1.SetRow(pb, i);
tableLayoutPanel1.SetColumn(pb, maxCol );
}
You can get the columns' Widths and the rows' Heights like this:
var widths = tableLayoutPanel1.GetColumnWidths();
var heights = tableLayoutPanel1.GetRowHeights();
You can fine-tune the position by setting Margins, e.g.:
pb.Margin = New Padding(50, 20, 0, 0);
To change the Heights of the Rows you can either use the Designer or you'll can set its Height in the RowStyle of each Row:
tableLayoutPanel1.RowStyles[row].SizeType = SizeType.Absolute;
tableLayoutPanel1.RowStyles[row].Height = newHeight;
To make your table layout visible during your tests you may want to insert code like this in the CellPaint event:
private void tableLayoutPanel1_CellPaint(object sender, TableLayoutCellPaintEventArgs e)
{
Random R = new Random(1 + e.Row * 3 + e.Column * 7);
using (SolidBrush brush = new SolidBrush(
Color.FromArgb(99, Color.FromArgb( R.Next(123456789)))))
e.Graphics.FillRectangle(brush, e.CellBounds);
}
I have a datagridview in winform and would like to do two things. Resize the datagrid so that all columns are showen (no scrolls) based on the datagrid size resize the width of the winform.
tried the code below but it doesn't work*
int width = 0;
foreach (DataGridViewColumn col in information.Columns)
{
width += col.Width;
}
width += information.RowHeadersWidth;
information.ClientSize = new Size(width + 100,height);
Simple order of operations:
Set the AutoSizeColumnMode property of the DataGridView to AllCells.
Add the Width property of all the columns plus some slack for extra width from borders on the control, etc. (Maybe plus 2)
Set the Width property of the DataGridView to the width you calculated.
Set the form's Width to the Width of the DataGridView.
Up to you to actually code it.
EDIT: I am in front of a compiler now so I put this together:
Go into Visual Studio. Start a new Project. Don't put anything onto the form in the designer. Simply use this code in the initializer.
public Form1()
{
InitializeComponent();
// Create a DataGridView with 5 Columns
// Each column is going to sized at 100 pixels wide which is default
// Once filled, we will resize the form to fit the control
DataGridView dataGridView1 = new DataGridView();
for (int i = 0; i < 5; i++)
{
DataGridViewTextBoxColumn col = new DataGridViewTextBoxColumn();
dataGridView1.Columns.Add(col);
}
dataGridView1.Location = new Point(0, 0);
// Add the DataGridView to the form
this.Controls.Add(dataGridView1);
// Step 2:
// Figure out the width of the DataGridView columns
int width = 0;
foreach (DataGridViewColumn col in dataGridView1.Columns)
width += col.Width;
width += dataGridView1.RowHeadersWidth;
// Step 3:
// Change the width of the DataGridView to match the column widths
// I add 2 pixels to account for the control's borders
dataGridView1.Width = width + 2;
// Step 4:
// Now make the form's width equal to the conbtrol's width
// I add 16 to account for the form's boarders
this.Width = dataGridView1.Width + 16;
}
This code creates a DataGridView with five columns and then sizes the control and the form exactly as you requested. I followed the exact steps I outlined above (except for step 1 because I don't have any data in my columns).
This code works. So if yours is NOT working, there must be something else silly that you have going on and I can't help you.
Hello I found out how to get this working using the following code below. information is the datagrid and this is the form.
int width = 0;
this.information.RowHeadersVisible = false;
for (int i = 0; i < information.Columns.Count; i++)
width += information.Columns[i].GetPreferredWidth(DataGridViewAutoSizeColumnMode.AllCells, true);
int rows = 0;
this.information.RowHeadersVisible = false;
for (int i = 0; i < information.Rows.Count; i++)
rows += information.Rows[i].GetPreferredHeight(i, DataGridViewAutoSizeRowMode.AllCells, true);
information.Size = new Size(width +20, rows+50);
this.Width = width + 50;