I have a TableLayoutPanel on a form which has 8 columns and 8 rows. I'm trying to populate this table from a list of a user controls which each contain three labels. When I run the app, I can see it has been populated, but looking at the actual form, it is empty.
I've tried replacing the control with just a label, and they show up fine, it's just when I try to use the user control that it doesn't work.
This code runs in the Load method and generates a list of GridSquareModel, which is used to populate the user control. Each model has an X and Y position which relates to their cell on the table panel.
var startup = new StartupForm();
if (startup.ShowDialog() == DialogResult.OK)
{
var grid = new List<GridSquareModel>();
for (int i = 0; i < 64; i++)
{
Position pos = new Position();
pos.X = i % 8;
pos.Y = i / 8;
grid.Add(new GridSquareModel(pos));
}
RenderGrid(grid);
}
else
{
Application.Exit();
}
This method generates a GridSquareControl for every GridSquareModel in the list. The X and Y value in the position determines which cell they are added to.
private void RenderGrid(List<GridSquareModel> grid)
{
UIGrid.Clear();
GridTable.Controls.Clear();
foreach (var item in grid)
{
var control = new GridSquareControl(item)
{
Dock = DockStyle.Fill
};
GridTable.Controls.Add(control, item.Position.X, item.Position.Y);
//GridTable.Controls.Add(new Label
//{
// Text = "TEST"
//}, item.Position.X + 1, item.Position.Y + 1);
}
}
I have commented my attempt to replace the GridSquareModel with a Label, which worked. This should produce a table containing 64 controls but once it is loaded the table appears empty.
I'm an idiot. I created a constructor for GridSquareControl but it did not include the InitializeComponent method, so obviously it was not rendered. All is working as expected now.
Related
I'm writing an audit program and I've got a problem. I use DevExp on the list, if the staff is audited on the control part, I would like to put a red cross if the green tick is not audited. But I could not do it with DevExp. Could you help?
gridView1 view: http://i.hizliresim.com/7Dqd75.jpg
I tried them
for (int i = 0; i < gridView1.RowCount; i++)
{
if (gridView1.GetRowCellValue(i, colAUDITSTATUS).ToString() == "False")
{
gridView1.SetRowCellValue(i, colCHECK, btnCheck);
}
}
I have identified the okButton object in the properties of gridView1 in the In-place Editor Repository.
The code works fine, but it does not change.
Set the ColumnEdit proprety of colAUDITSTATUS column to an instance of RepositoryItemCheckEdit and handle it there (see the comments in my code).
var repositoryItemCheckEdit1 = new DevExpress.XtraEditors.Repository.RepositoryItemCheckEdit();
repositoryItemCheckEdit1.AutoHeight = false;
repositoryItemCheckEdit1.Caption = "Audited";
repositoryItemCheckEdit1.CheckStyle = DevExpress.XtraEditors.Controls.CheckStyles.UserDefined; // <-- important!!!!!
repositoryItemCheckEdit1.Images = imageList; // <--- put an image control on your form and add red and green icons in it
repositoryItemCheckEdit1.ImageIndexChecked = 0; // <-- depends on your indexes in imageControl
repositoryItemCheckEdit1.ImageIndexUnhecked = 1; // <-- depends on your indexes in imageControl
repositoryItemCheckEdit1.Name = "repositoryItemCheckEdit1";
colAUDITSTATUS.ColumnEdit = this.repositoryItemCheckEdit1;
I am dynimically populating a panel with a table and adding some rows, columns, images and labes into the table based on the number of attached monitors. Each time the 'Monitors' panel is opened up, the dynimically added controls are removed and then re-added again in case any settings have been changed since it was last opened. When the panel is loaded for the first time, this is how it appears:
This is just how I want it to display. Both monitors detected and correct resolutions specified. Now, when the the Monitors panel is navigated away from, then switched back to (triggering the table contents to be removed and re-added), it displays with an extra row and old label like so:
No matter how many times the panel is navigated away from and back to, it always displays correctly the first time it's opened, then incorrectly any time after. Here is my code for populating the panel:
public void monitorPanel_Paint()
{
// Remove existing monitor pictures
foreach (Control item in monitorLayoutPanel.Controls.OfType<PictureBox>())
{
monitorLayoutPanel.Controls.Remove(item);
item.Dispose();
}
// Remove existing monitor labels
foreach (Control item in monitorLayoutPanel.Controls.OfType<Label>())
{
monitorLayoutPanel.Controls.Remove(item);
item.Dispose();
}
// Get number of attached monitors
int screens = Screen.AllScreens.Count();
// Auto add a table to nest the monitor images and labels
this.monitorLayoutPanel.Refresh();
this.monitorLayoutPanel.ColumnStyles.Clear();
this.monitorLayoutPanel.RowStyles.Clear();
this.monitorLayoutPanel.ColumnCount = screens;
this.monitorLayoutPanel.RowCount = 2;
this.monitorLayoutPanel.AutoSize = true;
int z = 0;
foreach (var screen in Screen.AllScreens.OrderBy(i => i.Bounds.X))
{
var percent = 100f / screens;
this.monitorLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, percent));
PictureBox monitor = new PictureBox
{
Name = "MonitorPic" + z,
Size = new Size(95, 75),
BackgroundImageLayout = ImageLayout.Stretch,
BackgroundImage = Properties.Resources.display_enabled,
Anchor = System.Windows.Forms.AnchorStyles.None,
};
Label resolution = new Label
{
Name = "MonitorLabel" + z,
TextAlign = ContentAlignment.MiddleCenter,
Font = new Font("Segoe UI", 10),
ForeColor = Color.Black,
BackColor = Color.Transparent,
Text = screen.Bounds.Width + "x" + screen.Bounds.Height,
Anchor = System.Windows.Forms.AnchorStyles.None,
};
this.monitorLayoutPanel.Controls.Add(monitor, z, 0);
this.monitorLayoutPanel.Controls.Add(resolution, z, 1);
z++;
}
}
I am surprised it isn't throwing an exception when you remove the controls from the Controls collection while enumerating it. It's worth checking if that is causing the enumeration to get clobbered and causing you to skip removing some of the controls. If that is the case, the solutions is capture a List<Control> of controls to remove while enumerating, then remove them all after enumerating it:
List<Control> controlsToRemove = new List<Control>();
foreach (Control item in monitorLayoutPanel.Controls.OfType<PictureBox>()) {
controlsToRemove.Add(item);
}
foreach (Control item in monitorLayoutPanel.Controls.OfType<Label>()) {
controlsToRemove.Add(item);
}
foreach (Control item in controlsToRemove) {
monitorLayoutPanel.Controls.Remove(item);
item.Dispose();
}
I have created a form that has generated several UserControls. There has to be an unlimited amount that can be added - there wont necessarily, but there needs to not be a cap on the amount.
I have used the following code to add them:
for (int i = 0; i < ucCount; i++)
{
UserControl1 uc = new UserControl1();
uc.name = "uc" + i.ToString();
flowLayout.Controls.Add(uc);
uc.Click -= new EventHandler(uc_Click);
uc.Click += new EventHandler(uc_Click);
}
ucCount is simply a variable to change the amount that are added.
The problem I'm having now, is I have a method in the UserControls that needs to be run when a button is pressed. This is the code for the following method:
public void ResizeTrucks()
{
...
}
Normally, if I had added the controls with a special name, I would have done the following:
uc.ResizeTrucks();
Since I added them in the code, and changed their names, I can no longer do that.
I now have the following code to change the size of all the usercontrols.
foreach (Control c in flowTrucks.Controls)
{
c.Width = 103;
c.Height = 528;
}
Basically, the problem that I'm facing is running a function in a usercontrol that I have generated in code, so I can't just do uc1.ResizeTrucks();.
I think I remember reading somewhere that you can get the function by name and then run it, but I haven't been able to find it anywhere. Any help will be appreciated.
You want to cast to the appropriate user control type, and then you can run the function. Something like:
foreach (Control c in flowTrucks.Controls)
{
c.Width = 103;
c.Height = 528;
var x = c as UserControl1;
if (x == null) continue; // not a UserControl1
x.ResizeTrucks();
}
I have code that creates a button for each object in a list. When each object is created it is given a name that corresponds to the row and column (i.e. name = row1col2). Each button is generated dynamically, added to the grid and then the row/column are set. At a later time I need to gather the "selected" button data so I can perform actions on the data they represent. When I attempt to get the control data from the buttons everything is fine, except for the grid row/column data. It remains the same for all of the selected rows and columns in a grid.
Creating buttons:
for (int i = 1; i < row.StackCount+1; i++)
{
//create button for the column
stackButton = new Button();
stackButton.Height = ((newRow.Height - 2));
stackButton.Width = ((newRow.Width / row.StackCount) - 2);
stackButton.Background = new SolidColorBrush(Colors.White);
//add the button border
stackButton.BorderBrush = new SolidColorBrush(Colors.Black);
stackButton.BorderThickness = new Thickness(1);
stackButton.Style = Application.Current.Resources["flatButton"] as Style;
//add the button name
stackButton.Name = "Row" + row.LineNumber + "Col" + (i - 1).ToString();
//add the event handler to the button
stackButton.Click += new RoutedEventHandler(stackButton_Click);
//add a new column
newRow.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(newRow.Width, GridUnitType.Star) });
//put the button into the grid
newRow.Children.Add(stackButton);
Grid.SetRow(stackButton, 0);
Grid.SetColumn(stackButton, i-1);
}
Getting the Button data back
g = (Grid)b.Child;
foreach (Button currentButton in g.Children)
{
if (((SolidColorBrush)currentButton.Background).Color == Colors.Gray)
{
//create a stack object
buttonData.StartDate = DateTime.Now;
buttonData.LotNumber = LotDisplay.Text;
buttonData.RoomID = SilverGlobals.CurrentRoom.RoomID;
buttonData.RoomCol = Grid.GetColumn(currentButton);
buttonData.RoomRow = Grid.GetRow(currentButton);
buttonData.TrayCount = int.Parse(currentButton.Content.ToString());
buttonData.Status = 0;
//add stack object to list of stack objects
stacks.Add(buttonData);
}
}
I know this must be something small I am missing. Anyone got any ideas?
Although the comment in your second section of code says:
//create a stack object
you don't actually create a new stack object so it is simply overwriting the single instance of buttonData on each iteration. The values for row and column that you see at the end are the last iteration's values.
The net effect is that stacks is a collection of all the same instance of an object instead of a collection of separate instances.
This is just a shot in the dark, but based on this question and this question, it might be that you need to set the Row and Column properties before you add the button to its parent - something like this:
//put the button into the grid
Grid.SetRow(stackButton, 0);
Grid.SetColumn(stackButton, i-1);
newRow.Children.Add(stackButton);
My tablelayout panel has one column and three rows. (one docked to Fill panel in each cell.)
Now I would like to be able to hide/show the rows . I want only one row to be visible at any time ( based on a user selection of some radio buttons) and I want to to get resized so it fills all the area of the TableLayoutPanel.
How can I do that? Any thoughts?
If rows in your TableLayoutPanel is autosized then hiding content panel will hide cell where panel placed too.
I would suggest setting the other rows heights to 0 is the easiest way:
Row one:
this.tableLayoutPanel1.RowStyles[1].Height = 0;
Try this
TableLayoutPanel1.ColumnStyles[1].SizeType = SizeType.Absolute;
TableLayoutPanel1.ColumnStyles[1].Width = 0;
So why did you use a TableLayoutPanel?
Just put three Panels on your form, fill in everyone the content of each row and set the Dock property of all three panels to Fill. Set two panels Visible = false and one to true.
If you like to see another panel, just make it visible and hide the other two (based on your radio button settings).
My scenario is similar. I needed a TableLayoutPanel with 4 rows each of which needed to be visible according to a checkbox selection. So instead of only showing one row at a time, I can show 1 - 4.
After designing the layout with 1 column and 4 rows, the controls were added and Dock set to Fill for each one.
Then in a single CheckedChanged event handler for the checkboxes, I coded as shown below. It's kind of a brute force method, but, Hey...it works!
private void checkBox_CheckedChanged(object sender, EventArgs e)
{
this.SuspendLayout();
int seldCount = checkBox1.Checked ? 1 : 0;
seldCount += checkBox2.Checked ? 1 : 0;
seldCount += checkBox3.Checked ? 1 : 0;
seldCount += checkBox4.Checked ? 1 : 0;
float pcnt = 0;
if (seldCount == 1)
pcnt = 1;
if (seldCount == 2)
pcnt = 0.5f;
if (seldCount == 3)
pcnt = 0.33f;
if (seldCount == 4)
pcnt = 0.25f;
int newHeight = (int)(tableLayoutPanel1.Height * pcnt);
if (checkBox1.Checked)
{
tableLayoutPanel1.RowStyles[0].SizeType = SizeType.Percent;
tableLayoutPanel1.RowStyles[0].Height = newHeight;
}
else
{
tableLayoutPanel1.RowStyles[0].SizeType = SizeType.Absolute;
tableLayoutPanel1.RowStyles[0].Height = 0;
}
if (checkBox2.Checked)
{
tableLayoutPanel1.RowStyles[1].SizeType = SizeType.Percent;
tableLayoutPanel1.RowStyles[1].Height = newHeight;
}
else
{
tableLayoutPanel1.RowStyles[1].SizeType = SizeType.Absolute;
tableLayoutPanel1.RowStyles[1].Height = 0;
}
if (checkBox3.Checked)
{
tableLayoutPanel1.RowStyles[2].SizeType = SizeType.Percent;
tableLayoutPanel1.RowStyles[2].Height = newHeight;
}
else
{
tableLayoutPanel1.RowStyles[2].SizeType = SizeType.Absolute;
tableLayoutPanel1.RowStyles[2].Height = 0;
}
if (checkBox4.Checked)
{
tableLayoutPanel1.RowStyles[3].SizeType = SizeType.Percent;
tableLayoutPanel1.RowStyles[3].Height = newHeight;
}
else
{
tableLayoutPanel1.RowStyles[3].SizeType = SizeType.Absolute;
tableLayoutPanel1.RowStyles[3].Height = 0;
}
this.ResumeLayout();
}
To hide row try this!!
tableLayoutPanel1.RowStyles[1].SizeType = SizeType.Absolute;
tableLayoutPanel1.RowStyles[1].Height = 0;
I had similar task to do and my solution is following:
Add a TableLayoutPanel to your form (or any container).
Set TableLayoutPanel's columns and rows count to 1 and size to 100%.
Set Dock to Fill.
Set GrowStyle to fixedSize.
Set AutoSize to true.
Then programmatically add all of three forms/controls, one of which you have to show depending on radio button choice. Be sure that only one of them is visible. That could be done with initial FirstControl.Show(); and then on each RadioButton event hide the current one and show another. you may "remember" in local variable (say: "currentlyVisibleControl" the reference which is currently visible)
note: if you will .Show() more than one at time. then TableLayoutPanel wil fire the exception that it is full and can't add any more item.
P.S. In My own example I have TableLayoutPanel in MDI window and three forms which substitute each other on button clicks on them so I think copying my source code will complicate the "verbal" example.
P.P.S. From my experience Visual Studio does some weird things in design mode sometimes. I had to remove and re-add the TableLayoutPanel to set properties correctly and get the results both in designer and in runtime. So if either autosize or absolute/percent values are not depicted on designer screen it may be designers problem rather that yours. JUST DELETE IT AND RETRY.
I tried fooling around with the Height and SizeType properties, but it was giving me odd results. For example, the Labels on the target row were being hidden, but the TextBoxes were not.
Here is an extension class that I came up with using #arbiter's suggestion of hiding the children Controls of the row.
// these methods only works on rows that are set to AutoSize
public static class TableLayoutPanelExtensions
{
public static void HideRows(this TableLayoutPanel panel, params int[] rowNumbers)
{
foreach (Control c in panel.Controls)
{
if (rowNumbers.Contains(panel.GetRow(c)))
c.Visible = false;
}
}
public static void ShowRows(this TableLayoutPanel panel, params int[] rowNumbers)
{
foreach (Control c in panel.Controls)
{
if (rowNumbers.Contains(panel.GetRow(c)))
c.Visible = true;
}
}
}