Add dynamic labels and textboxes from a checkedListBox - c#

I have a checkedListBox, that contains names of some chargingstations i have in a SQL database. I have filled the checkedListBox with the station names, and i would like that if you check an item in the box, a label with the text "Km to "+itemsChecked.StationName would appear just below the checkedListbox, as well as a textBox, where one would enter the kilometers to the station.
It's being used to create a new charging station, and the kilometers are the cost of the edge to the next station.
I've tried something like this:
private void stationCheckedListBox_SelectedIndexChanged(object sender, EventArgs e)
{
foreach (BetterServiceReference.Station itemsChecked in stationCheckedListBox.CheckedItems)
{
var lbl = new Label();
lbl.Name = "lblAuto" + itemsChecked.StationId;
lbl.Text = "Km to " + itemsChecked.StationName;
lbl.AutoSize = true;
lbl.Location = new Point(33, 462);
lbl.Name = "label1";
lbl.Size = new Size(35, 13);
tabPage7.Controls.Add(lbl);
}
Only it doesn't actually create a label.

I created a sample program, and it seems to work fine for me:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void checkedListBox1_SelectedIndexChanged(object sender, EventArgs e)
{
foreach (var item in checkedListBox1.CheckedItems)
{
Label lbl = new Label();
lbl.Text = "Testing";
lbl.Location = new Point(125, 125);
this.Controls.Add(lbl);
}
}
}
Some things to check / try:
Make sure the location of your label is not behind some other control!!
Use var / object instead of "BetterServiceReference.Station"
Is tabPage7 the name of your form? Try using this.Controls.Add(lbl);
I will also warn you that your function will not remove the labels once an item is unchecked. Also, as-is, it will only create one label in one spot for any checkbox checked. It's going to take a bit of work to implement what you are trying to do; as the other answer suggested, you may be better off toggling controls between visible / invisible.
But, hopefully my answer will help you dynamically create a label, and creating the textboxes will be very similar.

I think you need to create the label in the designer and make it Visible="False". Then in your code, make it Visible="True" as needed. Same with the textbox.

Related

C# User generated Label, that can be selected and its properties changed

I am trying to develop a software for designing and generating batches of IDs for schools etc. On the design part, a user would be able to create any number of text fields, select them, drag them around and/or nudge them with the arrow keys and edit their properties like text, font, size, and location. What I am trying to achieve is a much simpler version of the Visual Studio form designer. Here is a screenshot of my UI
So far, I have created a User Control called 'UserLabel' that inherits the Label class (I like Label because I can set the background transparent). A new UserLabel can be created by clicking the 'Add Text' button and can be dragged around the picture box.
public partial class UserLabel : Label
{
private System.Drawing.Point StartPoint;
private bool IsMouseDown = false;
public UserLabel()
{
InitializeComponent();
this.Text = "New Item";
this.AutoSize = true;
this.BackColor = System.Drawing.Color.Transparent;
this.Font = new System.Drawing.Font("Arial", 12);
this.Location = new System.Drawing.Point(5, 5);
this.Size = new System.Drawing.Size(50, 20);
}
protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
IsMouseDown = true;
this.BringToFront();
StartPoint = e.Location;
}
}
protected override void OnMouseUp(System.Windows.Forms.MouseEventArgs e)
{
IsMouseDown = false;
}
protected override void OnMouseMove(System.Windows.Forms.MouseEventArgs e)
{
if (IsMouseDown)
{
this.Left = e.X + this.Left - StartPoint.X;
this.Top = e.Y + this.Top - StartPoint.Y;
}
}
}
But since Label is not selectable, I have no clue how to proceed from here. I have tried adding a BorderStyle when the item is selected (see below) to give visual cues to the user which item is selected. But this does not achieve anything as far as being able to edit the properties. And I couldn't even manage to remove the BorderSyle to indicate a loss of focus.
protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
IsMouseDown = true;
this.BringToFront();
StartPoint = e.Location;
this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
}
}
Can anyone please point me in the right direction as to how I can override the CanFocus property (or Selectable property, I have no clue) or any other suggestion on how to achieve this? I am also open to any other approach to achieve my goal.
NOTE: I have tried a different approach where there will be a set number of items that are hidden and can be set visible by user like this. But I don't like this as it is repetitive and even though 10 items seem plenty, I can never know if a user might need more than this.
You do not have to hide/show any static number of rows, it is a bad design choice. All you need is use a DataGridView and a Button to add rows to the DataGridView. This way users can type anything they want into your textboxes and select from combobox of the row whatever they want to choose, also use a submit button to push code to db/render it on ui wherever you want to. Sample code might look like this-
private void button1_Click(object sender, EventArgs e)
{
DataGridViewColumn dataGridViewColumn = new DataGridViewColumn(new DataGridViewTextBoxCell()) ;
this.dataGridView1.Columns.Add(dataGridViewColumn);
DataGridViewColumn dataGridViewColumn2 = new DataGridViewColumn(new DataGridViewComboBoxCell());
this.dataGridView1.Columns.Add(dataGridViewColumn2);
DataGridViewRow dataGridViewRow = new DataGridViewRow();
dataGridViewRow.Cells.Add(new DataGridViewTextBoxCell());
this.dataGridView1.Rows.Add(new DataGridViewRow());
}

Using tag in datagridview

I want to do something like this with windows forms:
Something like tags, but I only want label without colors and "x" value, I just want label with click event, how can I do it without using Telerik? it's not possible to do in datagrid view or something like that? Regards
Tag is a very common .Net property, so the question is bit unclear. But looking at the image and taking a wild guess on what you may want..:
If you want to have the ability to add Labels, let's call them TagLabels during runtime you may want to use a FlowLayoutPanel as their container. It will allow adding more and will take care of the layout no matter what sizes they have.
Example:
To create them we can use a TextBox, which we add to the FLP first. Then we code its PreviewKeyDown event and let the user create a new TagLabel by pressing enter..:
private void textBox1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e.KeyCode == Keys.Enter && textBox1.Text != "")
{
Label lbl = new Label {
Text = " " + textBox1.Text, /* some room for the image */
BorderStyle = BorderStyle.Fixed3D,
TextAlign = ContentAlignment.MiddleCenter,
AutoSize = true,
Margin = new Padding(2),
ImageIndex = flowLayoutPanel1.Controls.Count %
imageList1.Images.Count,
ImageList = imageList1,
ImageAlign = ContentAlignment.MiddleLeft,
MinimumSize = new Size(100, 20),
BackColor = Color.LightGoldenrodYellow,
Name = "TagLabel" + (flowLayoutPanel1.Controls.Count)
};
lbl.MouseClick +=lbl_MouseClick ;
flowLayoutPanel1.Controls.Add(lbl);
flowLayoutPanel1.Controls.SetChildIndex(lbl,
flowLayoutPanel1.Controls.Count - 2);
textBox1.Text = "";
}
else
if (e.KeyCode == Keys.Escape)
{
textBox1.Text = "";
}
}
The Click event should be generic for all labels; so we first cast sender to Label and can then code the processing..:
private void lbl_MouseClick(object sender, MouseEventArgs e)
{
Label lbl = sender as Label;
//...
MessageBox.Show(lbl.Name + " : Ouch! You clicked on " + lbl.Text.Trim());
}
This is just a basic piece of code. You can style the labels any way you want and of course also include code for deleting, maybe with a context menu. If those labels shall carry more responsibility, you can and should create a class, probably a Label subclass to hold further data and methods..
I'm also using an ImageList to display images to the left. Do change these details to suit your needs!
Note that there is no reasonable way to add the FLP to an ordinary DataGridView. You may be able to workaround but depending on your needs it may be best to keep them separate. DGVs have Cells and while these can hold special controls this is complicated and will always be restricted by the cells' i.e. the Columns' and the Rows' Size. As an alternative you can check out this example to see how you can insert virtual space to a row to hold a control but neither DGV nor its Cells are containers.

Data binding to list and dynamically adding controls using Windows Forms

I have a List<Appointment> where an Appointment is.
public class Appointment
{
public string Title { get; set; }
public string Start { get; set; }
public string End { get; set; }
}
I want to dynamically add each list item on a separate line on the form like so:
item.Title + " between" + item.Start + " and " + item.End;
I want to be able to click each item (the text), then with each click it can toggle the colour of the text between red and black (that is, if black it turns red, if red it turns black when you click).
I come from a web background, but I am just struggling with Windows Forms data binding. I've tried with table layout panel but just don't know where to begin with changing the color of an item on click.
PS: If it helps, the number of items in the list will probably not be more than 10.
I've gotten a bit further as per Jamie Ide's comment:
var appts = GetAllCalendarItems();
foreach (var item in appts)
{
Label label = new Label();
label.Text = item.Title + " between" + item.Start + " and " + item.End;
label.Click += new EventHandler(label_Click);
flowLayoutPanel1.Controls.Add(label);
}
...
private void label_Click(object sender, EventArgs e)
{
// This is wrong - what goes here??
((Label)sender).ForeColor = Color.Red;
}
Dynamically laying out Windows Forms is a huge pain. I don't have time to code this but the steps are:
Add FlowLayoutPanel to form as a container
Look through your Appointments and create label controls for each
Add the label controls to the panel's Controls collection
Assign an OnClick handler to each label control to toggle the color
Don't bother with databinding for this.
If you haven't changed the label's initial color from the default, this will toggle it:
private void label1_Click(object sender, EventArgs e)
{
var lbl = (Label)sender;
var toggle = lbl.ForeColor == SystemColors.ControlText;
lbl.ForeColor = toggle ? Color.Red : SystemColors.ControlText;
}
You could add each text field as a member of a Label or List view item. Then handle the "OnClick" or "SelectedIndexChanged" event. To create an an OnClick event handler double click on the control in the design view. Edit the handler like this:
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
listView1.SelectedItems[0].ForeColor = Color.Red;
}
If you are unsure about event handlers, don't be put off they are quite easy, just look them up here perhaps. If the list view is not what you are looking for, try the same approach on a different control.
I guess I can't comment on Jamie's answer, but raklos you can programmatically add the OnClick method by doing:
label.Click += new EventHandler(label_Click);
Visual Studio should auto-generate the stubs for you when you start typing that out.
Something like this could get you started:
private void label_Click(object sender, EventArgs e) { ToggleTextColor((Label)sender); }
private void ToggleTextColor(Control control)
{
var currentColor = control.ForeColor;
control.ForeColor = currentColor == Color.Red ? Color.Black : Color.Red;
}
You can cheat and make create it in a WebBrowserControl.
You will be in familiar ground.
Use ObjectforScripting for WeBbrowser <=> winforms communication.
http://msdn.microsoft.com/en-us/library/system.windows.forms.webbrowser.objectforscripting.aspx

Create controls dynamically

I want to know if this is possible in c# winform.
create control when ever button is pressed and place it at given location.
I think it is possible like this
private TextBox txtBox = new TextBox();
private Button btnAdd = new Button();
private ListBox lstBox = new ListBox();
private CheckBox chkBox = new CheckBox();
private Label lblCount = new Label();
but the problem lies when ever button is pressed same name controls are created.How to avoid that
What da........
i wrote and no exception i was expecting it because control already contains btnAdd instead as many button create as many you want.
Accessing them will be issue but it will be solved by #drachenstern method correct?
private void button1_Click_1(object sender, EventArgs e)
{
Button btnAdd = new Button();
btnAdd.BackColor = Color.Gray;
btnAdd.Text = "Add";
btnAdd.Location = new System.Drawing.Point(90, 25+i);
btnAdd.Size = new System.Drawing.Size(50, 25);
this.Controls.Add(btnAdd);
i = i + 10;
}
int currentNamingNumber = 0;
txtBox.Name = "txtBox" + currentNamingNumber++;
Rinse, Repeat.
Gives each element a unique numeric name, allows you to find out how many elements have been created (notice that you don't want to decrement to track all created objects, because then you may create two elements with the same name).
I don't think you can pass the name you want into the new function, but you can always set the name after creating it.
You could try the solution I posted here. It will dynamically create 5 buttons in the constructor. Just move the code to the button click event and it should add the buttons dynamically and register with the Click events.
It sounds like your looking for a List<TextBox>.

Select text from multiple textboxes simultaneously

i have 10 textboxes and i need to select text from each one of them.
The problem is that i cant select text from multiple textboxes.
Is there any solution for this problem my code is.
private void Form1_Load(object sender, EventArgs e)
{
createTextBoxes(10);
((TextBox)textBoxes[0]).Select(1, 4);
((TextBox)textBoxes[1]).Select(1, 4); // <- it will not select text
((TextBox)textBoxes[2]).Select(1, 4); // same here
}
Control[] textBoxes;
private void createTextBoxes(int cnt)
{
textBoxes = new Control[cnt];
for (int i = 0; i < cnt; i++)
{
TextBox tb = new TextBox();
tb.Name = i.ToString();
tb.Location = new Point(5, 5 + 14 * i);
tb.Size = new Size(600, 20);
tb.BorderStyle = BorderStyle.None;
tb.Text = "sample text" + i.ToString();
textBoxes[i] = tb;
this.Controls.Add(tb);
}
}
Set the HideSelection property of the texboxes to false. They will maintain selection after losing focus.
Only one control can have a "Focus" at a time... you can't select (ie:highlight) text of multiple controls.
I also just tested by adding a button to the form and posted your 3 "select" snippets there too... nothing showed highlighted. However, when I did a TAB through each control, the first 3 respectfully showed the highlighted section. When I tabbed through the rest, the entire field of the rest of the textboxes were fully selected.
Or are you really trying to accomplish something else...
The text is selected you just can't see it cause of focus.
I ran your code and after doing so tabbed through the controls. The first 3 are selected as specified.
This is possibly not working because even though you've added the TextBox instances to the Form, they have not yet been displayed. Until they are displayed and initially rendered it's likely not possible to initiate a selection on them.
Actually it does, the problem is that the other 2 of your textboxes ([1] and [2]) don't have focus. Only one control can have focus at a time. If you hit tab to give focus to the next TextBox, you'll see the text selected.

Categories