I'm trying to create components on the fly, so, I know how to make this, but, how can I access this component on the fly?
For example:
public Form1
{
Label label1 = new Label();
label1.AutoSize = true;
label1.Location = new System.Drawing.Point(e.X, e.Y);
label1.Name = string.Format("label{0}", labelsCount.ToString());
label1.Size = new System.Drawing.Size(35, 13);
label1.TabIndex = 2;
label1.Text = string.Format("Label -> {0}", labelsCount.ToString());
label1.Click += new System.EventHandler(this.label1_Click);
this.Controls.Add(label1);
label1.BringToFront();
label1.Show();
labelsCount++;
}
When I click on the label, I want to get the label's information (like position, text and name)
How I can do this? Or, what is the best way to do this?
And, to access the component based on position of the panel, inside of form, how I can do this?
Sender of event is your lablel. Simply cast sender object to Label type:
void label1_Click(object sender, EventArgs e)
{
Label label = (Label)sender;
// use
// label.Name
// label.Location
}
Related
I'm building that To-Do list app and I'm trying to create a "Add New task" button.
I wanted to create a new Task (TextBox) on the button click and also move the button bellow the TextBox added. So, I tried to create multiple panels and when the button was clicked, move the "New Task" button to the second panel and add the new textbox created to the first panel. And after that if the user wanted to remove that Task (TextBox), to repositionate the button and Tasks according to that.
Can someone please help me with that??
`
private void btnNewTask_Click(object sender, EventArgs e)
{
// Creating new Textbox
TextBox txtTask = new TextBox();
btnNewTask.Location = new Point(panel2);
// txtTask parameter
txtTask.BorderStyle = BorderStyle.None;
txtTask.ReadOnly = false;
txtTask.PlaceholderText = "Input a new Task.";
txtTask.Location = new Point(panel1);
//Adding txtTask.
this.Controls.Add(txtTask);
}
`
I founded The Solution. I deleted the panels and leaved the btnNewTask on the form.
On button click I needed to create and set the txtTask location as the btnNewTask location and change the Y location of btnNewTask to move it bellow. After that check if there was any other control that had the same or less Y location than txtTask, and if there was any, add 35 to his Y location too.
There is my new Code:
int c = 0;
private void btnNewTask_Click(object sender, EventArgs e)
{
// Creating new Textbox
TextBox txtTask = new TextBox();
// txtTask parameter
Font font = new Font("Segoe UI", 10.0f);
txtTask.Name = "txtTask" + ++c;
txtTask.BorderStyle = BorderStyle.None;
txtTask.ReadOnly = false;
txtTask.PlaceholderText = "Input a new Task.";
txtTask.Size = new Size(817, 31);
txtTask.Font = font;
txtTask.Location = new Point(btnNewTask.Location.X , btnNewTask.Location.Y); // txtTask will get the "btnNewTask" Location
btnNewTask.Location = new Point(txtTask.Location.X , btnNewTask.Location.Y + 35); // That should add 35 to the Y location
foreach (Control item in this.Controls)
{
if (item.Location.Y >= txtTask.Location.Y)
{ // if there is an item that has greater Y location
item.Location = new Point(item.Location.X, txtTask.Location.Y + 35); // It should increase its value as 35 too.
}
this.Controls.Add(txtTask);
}
There's an example:
Thank for the help and ideas!
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.
We just started learning winforms and we have to make a mock GUI. With a contextMenuStrip I can make new labels which look like folders.
private void makeFolder(int x, int y)
{
Label lbl_folder = new Label();
lbl_folder.Location = new Point(x, y);
lbl_folder.Width = 75;
lbl_folder.Height = 75;
lbl_folder.BackColor = Color.Transparent;
lbl_folder.Image = Properties.Resources.folder;
lbl_folder.Text = "New Folder" + folderindex;
lbl_folder.TextAlign = ContentAlignment.BottomCenter;
canvas.Controls.Add(lbl_folder);
folderindex++;
lbl_folder.ContextMenuStrip = folderMenuStrip; //so I can use another contextMenuStrip on them
}
With another contextMenuStrip used on these folders, I would like for example to delete the right-clicked folder but I can't reach lbl_folder.
//I would like to do something like this
private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
{
lbl_folder.Hide();
}
The name lbl_folder doesn't exists in the current context. How can I fix this?
You declared lbl_folder in local scope (within a method) so you can only use that variable within it. You have two options:
Declare the variable at form scope. So move the line Label lbl_folder = new Label(); outside of makeFolder.
private Label lbl_folder = null;
private void makeFolder(int x, int y)
{
lbl_folder = new Label();
Inside of deleteToolStripMenuItem_Click, retrieve a new reference to the same control, via the form's ControlCollection, e.g.
var lbl = this.Controls.Find("NameOfControl", true)[0] as Label;
or
var lbl = this.Controls.Find("NameOfControl", true).OfType<Label>().Single();
...depending how comfortable you are with LINQ.
You might also be able to get it from canvas more efficiently, depending how you have canvas scoped.
var lbl = canvas.Controls.Find("NameOfControl")[0] as Label.
Since you are creating labels dynamically and attaching the context menu to each label, I suspect what you really want is the delete menu item to reference the label you are right clicking.
In that case, you can use the SourceControl of the ContextMenuStrip to provide that:
private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
{
((Label)folderMenuStrip.SourceControl).Visible = false;
}
Its an issue about the scopes of your labels. If they were declared in your makeFolder method they you cannot be accessed from outside the method.
If you don't want to use the FindControls method of the Container. Then, you can keep references to your labels created in a hashtableor dictionary which is declared as instance property in the form itself.
Then, in your makeFolder add the label to it.
lbl_folder.Name = folderindex;
hashtable.Add(lbl_folder.Name, lbl_folder);
From anywhere in the form you can get the label from you hashtable and modify its properties.
private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
{
var menuItem = sender as ToolStripMenuItem;
var menu = menuItem.GetCurrentParent() as ContextMenuStrip;
var label = menu.SourceControl as Label;
label.Visible = false;
}
You can also do this inside the makeFolder method:
lbl_folder.Click += (s, e) => lbl_folder.Hide();
I understand that this isn't the event that you're trying to respond to, but it should help you to understand how it can be done.
So your method would look like:
private void makeFolder(int x, int y)
{
Label lbl_folder = new Label();
lbl_folder.Location = new Point(x, y);
lbl_folder.Width = 75;
lbl_folder.Height = 75;
lbl_folder.BackColor = Color.Transparent;
lbl_folder.Image = Properties.Resources.folder;
lbl_folder.Text = "New Folder" + folderindex;
lbl_folder.TextAlign = ContentAlignment.BottomCenter;
lbl_folder.Click += (s, e) => lbl_folder.Hide();
canvas.Controls.Add(lbl_folder);
folderindex++;
lbl_folder.ContextMenuStrip = folderMenuStrip;
}
This works no matter how many time you call this method and how many folder are created.
I dynamic create and trackbar on an event,
now i want a textbox tto be filled with the value of the trackbar.
but how am i possible to do that? since i'll get an error saying the dynamic created trackbar does not exist. which is logic
this is what i have so far.
TrackBar trackBar = new TrackBar();
trackBar.Name = "TrackbarWidth" + trackbarName++;
trackBar.Tag = "dispose";
trackBar.Maximum = 85;
trackBar.Minimum = 65;
trackBar.SmallChange = 5;
trackBar.TickFrequency = 5;
trackBar.Value = WidthValue;
trackBar.Location = new Point(175, 440 + (50 * trackbarName));
trackBar.Size = new System.Drawing.Size(100, 25);
this.Controls.Add(trackBar);
TextBox textBox = new TextBox();
textBox.Name = "TrackbarWidth" + TextboxName++;
textBox.Text = trackBar.Value.ToString();
textBox.Tag = "dispose";
textBox.Location = new Point(300, 440 + (50 * TextboxName));
textBox.Size = new System.Drawing.Size(30, 25);
this.Controls.Add(textBox);
lineWidth += 4;
}
#endregion
}
private void trackBar1_Scroll(object sender, EventArgs e){
textBox1.Text = trackBar1.Value.ToString();
}
The problem with this solution is that I cannot access the textbox or the trackbar in the trackBar1_Scroll method.
The easiest solution here to use use an anonymous event handler that is capable of closing over the two variables that you need. Include this just after you finish constructing the textbox:
this.Controls.Add(textBox);
trackBar.Scroll += (s, args) => {
textbox.Text = trackbar.Value.ToString();
};
The sender argument is always the control which triggered the event:
private void trackBar_Scroll(object sender, System.EventArgs e)
{
// TextBox also dynamic? One way is using ControlCollection.Find
textBox1 = this.Controls.Find("textBox1", true).FirstOrDefault() as TextBox;
if(textBox1 != null)
textBox1.Text = trackBar1.Value.ToString();
}
However, if you create it dynamically you also have to create the event handler:
TrackBar trackBar = new TrackBar();
trackBar.Scroll += this.trackBar_Scroll;
I'm trying to do a notepad with chrome-like tabs on it. I have a "New Page" button on my page. When I click on it, it creates a new tabpage with a richtexbox on it. The richboxes are created like this
public void yeni()
{
//create a new tabpage
TabPage newPage = new TabPage("Not-" + (tabControl1.TabPages.Count + 1));
//create a new richtexbox
RichTextBox rtb = new RichTextBox();
int rtbname = tabControl1.TabPages.Count + 1;
rtb.Name = "richTextBox" + rtbname.ToString();
rtb.Anchor = (AnchorStyles.Bottom | AnchorStyles.Right | AnchorStyles.Left | AnchorStyles.Top);
rtb.BorderStyle = BorderStyle.None;
rtb.Width = 778;
rtb.Height = 395;
rtb.Location = new Point(0, 4);
rtb.HideSelection = false;
rtb.Font = new Font("Lucida Console", 9.75f);
rtb.ForeColor = Color.Maroon;
//add rtb to the tabpage
newPage.Controls.Add(rtb);
tabControl1.TabPages.Add(newPage);
//make the new created tab the selected one
tabControl1.SelectedTab = tabControl1.TabPages[tabControl1.TabPages.Count - 1];
//selectedRtb.Text = null;
openFileDialog1.FileName = null;
}
Now I create a RichTextBox and the name of that rtb is richTextBox*indexofthetabhere*. So if I'm working on the second tabpage, the name of the rtb is "richTextBox2". Now what I'm trying to do is I want an textchanged event for the richtextbox on the selected tabpage. I'm getting the selected richtextbox with this code here.
private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
selectedone = "richTextBox" + (tabControl1.SelectedIndex+1).ToString();
selectedRtb = (RichTextBox)tabControl1.SelectedTab.Controls[selectedone];
textBox2.Text = selectedone;
}
Now here I get the selected tab index and i get the rtb name then I get the selected rtb as "selectedRtb". Now I can't make a textchanged event for this. I don't know what to do actually. I tested if the above code was working and yes I get the rtb names right. But I can't use them because I don't know how to do.. Thanks for the help.
public void yeni()
{
//....
RichTextBox rtb = new RichTextBox();
rtb.Name = "richTextBox" + selectedTabPageIndex.ToString();
rtb.TextChanged += rtb_TextChanged;
//....
}
void rtb_TextChanged(object sender, EventArgs e)
{
RichTextBox rtb = (RichTextBox)sender;
if (rtb.Name == "richTextBox" + selectedTabPageIndex.ToString())
{
//rtb is selected page richtextbox
//......
}
}
You don't know how to create events? Or you can't access something while knowing it's name (use reflection)?
Alright I solved my problem. Here is the answer;
selectedRtb.TextChanged += (bs, be) =>
{
//whatever you want to do
};
Simply added this to my code after I created the rtb, and it worked. Thanks to everyone who helped.