C# : how to modify properties of dynamically created controls like panels etc - c#

I need help with modifying the properties of a dynamically created controls.
First I created 2 panels on the form dynamically like this:
public void create_panels()
{
Panel panel1 = new Panel();
panel1.BackColor = Color.Red;
panel1.Location = new Point(0, 0);
panel1.Size = new Size(320, 480);
this.Controls.Add(panel1);
Panel panel2 = new Panel();
panel2.BackColor = Color.Red;
panel2.Location = new Point(320, 0);
panel2.Size = new Size(320, 480);
this.Controls.Add(panel2);
}
The problem I can't seam to find any clear information about how to modify them after they where (dynamically) created. One would thinks that simply doing something like this below would be easy and nice: (to change the panels color and position). However, this obviously doesn't work since the panel was created dynamically:
panel1.BackColor = Color.Blue;
panel1.Location = new Point(320, 0);
Can someone please help post the simplest way to modify properties of dynamically made control (panel or textbox) changing the controls location or color after it has been created in a dynamic method?

If you still have a reference to the control, you can of course just set the properties directly, as in the following example. The trick is to save the reference as a form-scope variable (instead of as a local variable).
class SomeForm : Form
{
protected Panel _panel1;
public Form_Load(object sender, EventArgs e)
{
_panel1 = new Panel
{
BackColor = Color.Red,
Location = new Point(0, 0),
Size = new Size(320, 480)
};
this.Controls.Add(panel1);
}
public void Example()
{
_panel1.BackColor = Color.Blue; //Simple to change it if you have a reference already
}
}
If you don't want to keep a reference, you can also grab one from the Controls collection, like this:
class SomeForm : Form
{
public Form_Load(object sender, EventArgs e)
{
Panel panel1 = new Panel
{
Name = "SomeNameICanUse", //Important!
BackColor = Color.Red,
Location = new Point(0, 0),
Size = new Size(320, 480)
};
this.Controls.Add(panel1);
}
public void Example()
{
var panel1 = this.Controls.Find("SomeNameICanUse") as Panel; //use the name to find it
if (panel1 != null) panel1.BackColor = Color.Blue;
}
}

Related

C# Custom ComboBox - DropDown Position

I'm creating a ComboBox control using ToolStripControlHost and ToolStripDropDown that can host any kind of control in the DropDown window. For example, the DropDown window might display a listview or treeview or even another usercontrol.
I'm posting a simplified code below where dropdown host a usercontrol with a listview and a button like this:
The problem occurs when the control is positioned at the bottom of the screen in such a way that the dropdown window will extrapolate the lower boundary of the screen. When this occurs, the dropdown ends up hiding the control.
In this case, I'd like to fix the _dropDown.Show method call to show dropdown window as follows:
To repeat the problem, just run the code below and drag the window to the bottom of the screen and open the dropdown.
using System;
using System.Windows.Forms;
public class CustomComboBox : UserControl
{
ToolStripDropDown _dropDown;
public CustomComboBox()
{
var textbox = new TextBox();
textbox.Location = new System.Drawing.Point(0, 0);
textbox.Size = new System.Drawing.Size(this.Width - 22, 20);
textbox.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;
this.Controls.Add(textbox);
var button = new Button();
button.Location = new System.Drawing.Point(this.Width - 22, -1);
button.Size = new System.Drawing.Size(22, 22);
button.Text = "\u2BC6";
button.Anchor = AnchorStyles.Right | AnchorStyles.Top;
button.Click += new System.EventHandler(this.Button_Click);
this.Controls.Add(button);
var dropDownControl = new DropDownControlTest();
var controlHost = new ToolStripControlHost(dropDownControl);
_dropDown = new ToolStripDropDown();
_dropDown.AutoSize = true;
_dropDown.Items.Add(controlHost);
}
void Button_Click(object sender, EventArgs e)
{
_dropDown.Show(this, 0, this.Height);
}
}
public class DropDownControlTest : UserControl
{
public DropDownControlTest()
{
var listview = new ListView();
listview.Location = new System.Drawing.Point(3, 1);
listview.Size = new System.Drawing.Size(400,300);
listview.View = View.Details;
listview.Columns.Add("Col 1",100);
listview.Columns.Add("Col 2",100);
this.Controls.Add(listview);
var button = new Button();
button.Location = new System.Drawing.Point(3, 305);
button.Text = "More...";
this.Controls.Add(button);
}
}
public class Form1 : Form
{
private static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
public Form1 ()
{
CustomComboBox ccBox = new CustomComboBox();
ccBox.Location = new System.Drawing.Point(10, 10);
ccBox.Height = 20;
this.Text = "Test CustomComboBox";
this.Controls.Add(ccBox);
}
}
You can use the ToolStripDropDown.Show Method (Control, Point, ToolStripDropDownDirection) overload to control the drop direction. The code will need to perform bounds checking to decide whether to place the dropdown above or below the textbox.
The following is a simplistic method for doing the bounds checking and was only tested on a single screen configuration.
First, make textbox a class level variable.
private TextBox textbox;
public CustomComboBox()
{
//var textbox = new TextBox();
textbox = new TextBox();
The display logic is as follows.
void Button_Click(object sender, EventArgs e)
{
Point textBoxScreenLocation = textbox.PointToScreen(textbox.Location);
// try to position _dropDown below textbox
Point pt = textBoxScreenLocation;
pt.Offset(0, textbox.Height);
// determine if it will fit on the screen below the textbox
Size dropdownSize = _dropDown.GetPreferredSize(Size.Empty);
Rectangle dropdownBounds = new Rectangle(pt, dropdownSize);
if (dropdownBounds.Bottom <= Screen.GetWorkingArea(dropdownBounds).Bottom)
{ // show below
_dropDown.Show(pt, ToolStripDropDownDirection.BelowRight);
}
else
{ // show above
_dropDown.Show(textBoxScreenLocation, ToolStripDropDownDirection.AboveRight);
}
}
}
I can not comment that is why I am answering your question. You can use the reflection and then re-position you control. I have found a custom combobox control same as you developed. Please check this. At least, you will get some idea what you need to do.

Dynamically creating a picturebox from another class into a form

I'm having troubles with this part trying to create a picturebox into another form from another class, i hope I've provided enough information c:
Catelogue.cs <-- class that loads the picturebox
class Catelogue
{
public void loadCatelogue()
{
mainPageGUI u = new mainPageGUI();
PictureBox pictureBox1 = new PictureBox();
pictureBox1.Location = new System.Drawing.Point(0, 0);
pictureBox1.Name = "pictureBox1";
pictureBox1.Size = new System.Drawing.Size(500, 500);
pictureBox1.BackColor = Color.Red;
u.Controls.Add(pictureBox1);
MessageBox.Show("HI");
}
}
mainmenuGUI.cs < --- form that's calling loadcatelogue() to load picturebox
private void catelogueButton_Click(object sender, EventArgs e)
{
Catelogue a = new Catelogue();
a.loadCatelogue();
}
You are creating a new instance of the mainPageGUI form and add, to that instance, the new picturebox. This instance is not the one that calls your method and it is never showed. So your original instance remain unchanged and you don't see anything. (Just to demonstrate the problem try to change your MessageBox line with u.Show();)
To fix, just change your calling code and pass the form instance on which the picturebox should be created
private void catelogueButton_Click(object sender, EventArgs e)
{
Catelogue a = new Catelogue();
// pass this instance to the method....
a.loadCatelogue(this);
}
and of course use the instance passed
public void loadCatelogue(mainPageGUI u)
{
PictureBox pictureBox1 = new PictureBox();
pictureBox1.Location = new System.Drawing.Point(0, 0);
pictureBox1.Name = "pictureBox1";
pictureBox1.Size = new System.Drawing.Size(500, 500);
pictureBox1.BackColor = Color.Red;
u.Controls.Add(pictureBox1);
}

Dynamically Adding Class of Controls

I am having trouble with dynamically adding a class of controls that should when working look like this:
When a new one is added it should appear in the left panel under the toolstrip.
So far I am having trouble making them appear (The one in the middle is just the design I made).
Here is the code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
//Problem Occurs Here
EquationBox[] EquationBoxArray = new EquationBox[12];
for (int x = 0; x < 12; x++)
{
EquationBoxArray[x] = new EquationBox();
ActiveForm.Controls.Add(EquationBoxArray[x].mainPanel);
ActiveForm.Controls.Add(EquationBoxArray[x].colorPanel);
}
}
private void add_line_Click(object sender, EventArgs e) //Add Line
{
}
private void clear_Click(object sender, EventArgs e) //Clear Lines
{
}
}
public class EquationBox
{
public Panel colorPanel = new Panel();
public Panel mainPanel = new Panel();
public TextBox equationBox = new TextBox();
public CheckBox isVisibleBox = new CheckBox();
public EquationBox()
{
mainPanel.Size = new Size(200, 72);
colorPanel.Size = new Size(33, 72);
mainPanel.Location = new Point(50, 50);
colorPanel.Location = new Point(50, 50);
colorPanel.BackColor = Color.Red;
}
}
The problem occurs here:
//Problem Occurs Here
EquationBox[] EquationBoxArray = new EquationBox[12];
for (int x = 0; x < 12; x++)
{
EquationBoxArray[x] = new EquationBox();
ActiveForm.Controls.Add(EquationBoxArray[x].mainPanel);
ActiveForm.Controls.Add(EquationBoxArray[x].colorPanel);
}
When I run it, it return with:
Additional information: Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on.
And even before that started happening, the EqautionBox wouldn't appear.
Thanks in advance, this is really troubling me.
For the constructor of EquationBox:
public EquationBox()
{
mainPanel.Size = new Size(200, 72);
colorPanel.Size = new Size(33, 72);
mainPanel.Location = new Point(50, 50);
colorPanel.Location = new Point(50, 50);
colorPanel.BackColor = Color.Red;
}
First, your control appeared, but mainPanel is overlap colorPanel and you can't see mainPanel (same BG color as your form), so swap which added first solved
EquationBox[] EquationBoxArray = new EquationBox[12];
for (int x = 0; x < 12; x++)
{
EquationBoxArray[x] = new EquationBox();
this.Controls.Add(EquationBoxArray[x].colorPanel);
this.Controls.Add(EquationBoxArray[x].mainPanel);
}
I am using this.Controls, not sure about the ActiveForm.Controls part, maybe on constructing, your Form1 is not the active one, so error occured.
Ps: I suggest add colorPanel to mainPanel, and only add mainPanel to Form. And UserControl is a good solution here as Steve Wellens said.
There are various issues with EquationBox the TextBox and CheckBox are not in the panel. It would be easier to make it a UserControl.
Then to do the positioning use a FlowLayoutPanel.

Add controls dynamically from another class C#

I have a panel called mainPanel in my Form1 and I want to add controls to it from another class. I tried to set the visibility to public but it didn't work.
This is where I create my controls:
public List<Control> addControlsToMain(string SearchWord, Size ContainerSize)
{
List<Control> ListOfControls = new List<Control>();
Panel Box;
Label Title, Content;
int PositionCounter = 10;
foreach (string data in GetSearchData(SearchWord))
{
Box = new Panel();
Title = new Label();
Content = new Label();
Box.Size = new Size((int)(ContainerSize.Width * 0.8), 100);
Title.Size = new Size(Box.Width, 20);
Content.Size = new Size((int)(Box.Width * 0.8), 60);
Box.Location = new Point(10, PositionCounter);
Title.Location = new Point(25, 10);
Content.Location = new Point(25, 40);
Title.Text = "Title";
Content.Text = "Content here";
ListOfControls.Add(Box);
Box.Controls.Add(Title);
Box.Controls.Add(Content);
PositionCounter += 110;
}
return ListOfControls;
}
Where GetSearchData(SearchWord) is just another function that returns random strings in a list, this function addControlsToMain() belongs to my class SearchFunctions.cs (a class separated from the Form1). I've tried to add these controls doing this:
var mainForm = new Form1();
SearchFunctions src = new SearchFunctions();
System.Drawing.Size panelSize = mainForm.mainPanel.Size;
foreach(System.Windows.Forms.Control data in src.addControlsToMain("Stack overflow", panelSize))
{
mainForm.mainPanel.Controls.Add(data);
}
My class CommandFunctions.cs is who has to add these controls. How can I add these list of controls to my panel?
You could go about this a few ways. One of which would be to add a SearchFunctions object as a a property to your Form1 class. Then use that object to call the method that adds the controls.
public partial class Form1 : Form
{
SearchFunctions src = new SearchFunctions();
public void Button_Click(object sender, EventArgs e)
{
List<Control> myControls = src.addControlsToMain(mySearchWord, mySize);
foreach (Control c in myControls)
{
this.Controls.Add(c);
}
}
}
This example uses a button click but you would place that method anywhere you want.
The problem is most likely here:
var mainForm = new Form1();
You're creating a new instance of Form1 that never gets displayed.
Here are some options:
Pass a reference to your existing Form1 instance into your class and add the controls using that reference.
or
Use the addControlsToMain() function directly from the Form itself so you can add the controls using this as Juken has demonstrated in his post.
or
Pass the controls out to the form using a custom event.
I have rather used webform, but still, this should work: I am basically trying to add controls
To a ** Panel** (instead of Form)in one class(say Main.cs) And
Create and add the controls to this Panel from another class(say class1.cs)
========================================================================
Steps:
1.Make use of the appropriate namespaces for calling control class utility
ex: System.Web.UI.Web Controls (in my case)
2.In Main.cs
Panel Panel1= new Panel();
foreach(some condition)
{
class1.addControlsToMain("xyz_Searchword", 2, ref Panel1); //Calls the method which creates the controls
}
Class1.cs
{
Public static void addControlsToMain(string searchword, int size,ref Panel p1)
{
List<WebControl> list = new List<WebControl>(); //should be List<Control> for Windows
Label lb1, title;
lb1 = new Label();
title = new Label();
lb1.Text = "Test Label Control1";
title.Text = "Test Title Label Control";
p1.Controls.Add(lb1);
p1.Controls.Add(title);
list.Add(p1);
}
}
To cut the long story short, try using Ref keyword. Hope this helps in a bit.

Form based on selected menu item

I have made a sidebar that I dock on the left side of my application.
Now I'm wondering what's the best way to show a form based on the menu option they've selected from my sidebar.
This is basically what I want to do:
http://www.dreamincode.net/forums/topic/176782-building-an-application-poscash-register-part-one/
On the left is my menu bar, on the right side I want to have a form based on the option clicked on the left.
I have looked into MDI but when I do that I always get a ControlBox even though I've disabled it in the child form.
Update: Seems that this works as well:
Looks like you can also create your own user controls to do it:
User controls
If you want second wont allow you to access your main form unless its closed.then use this...
second_form_name sfn = new second_form_name();
sfn.ShowDialog();
If you want second allow you to access your main form unless its closed.then use
second_form_name sfn = new second_form_name();
sfn.Show();
First create a panel in your form that will hold your current form's contents (add it to the form but leave it empty for now).
Panel active = new Panel();
this.Controls.Add(active);
Then create a panel containing controls for each form you want to display.
Panel firstFormPanel = new Panel();
firstFormPanel.Add(new Button());
Panel secondFormPanel = new Panel();
secondFormPanel.Add(new Button());
Now assign which panel you want by default:
active = firstFormPanel;
Then when you want to change to a new form (click event in sidebar), assign one of the panels to the active panel like so:
active.Visible = false;
active = secondFormPanel;
active.Visible = true;
Here's a little example i have of a sidebar from my game im making being able to slide a new submenu into visual range. I use a timer to control movement and a list of submenus also a index to determine which to show. as far as i've gotten along theres only one so far so not a prime example.
public List<UserControl> Submenus = new List<UserControl>();
Multiplayer_Menu MPM;
enum At { Left, Right }
At Current = At.Right;
At Go_to = At.Right;
int Submenu_Index = 0;
bool done = false;
public void Load_Submenus()
{
Multiplayer_Menu MM = new Multiplayer_Menu(this);
MainMenu.Controls.Add(MM);
MM.Location = new Point(MainMenu.Size.Width, 0);
MM.Visible = false;
Submenus.Add(MM);
PictureBox PB = new PictureBox();
MainMenu.Controls.Add(PB);
PB.Location = new Point(MainMenu.Size.Width, 0);
PB.Size = new System.Drawing.Size(924, 736);
PB.SizeMode = PictureBoxSizeMode.StretchImage;
PB.ImageLocation = "http://www.taloreal.com/Earth%20Rotation/Rotating.gif";
PB.Visible = true;
}
private void Form1_Load(object sender, EventArgs e)
{
Load_Submenus();
}
public void MML_Multiplayer_Click(object sender, EventArgs e)
{
Submenus[Submenu_Index].Visible = false;
if (Current == At.Left)
Go_to = At.Right;
if (Current == At.Right)
Go_to = At.Left;
ShowHideMenus.Enabled = true;
Submenu_Index = 0;
}
private void ShowHideMenus_Tick(object sender, EventArgs e)
{
Point P = new Point(MainMenu.Location.X, MainMenu.Location.Y);
Size S = new Size(MainMenu.Size.Width, MainMenu.Size.Height);
if (Go_to == At.Left)
{
P = new Point(P.X - 30, P.Y);
S = new Size(S.Width + 30, S.Height);
if (P.X == 0)
{
Submenus[Submenu_Index].Visible = true;
ShowHideMenus.Enabled = false;
Current = Go_to;
}
}
if (Go_to == At.Right)
{
P = new Point(P.X + 30, P.Y);
S = new Size(S.Width - 30, S.Height);
if (P.X == 930)
{
ShowHideMenus.Enabled = false;
Current = Go_to;
}
}
Reposition_Menu(P, S);
}
void Reposition_Menu(Point P, Size S)
{
MainMenu.Location = P;
MainMenu.Size = S;
}

Categories