Is there a way that I could access a label with variable parameters? For example, I have a list of labels (lbl00, lbl01, lbl02, lbl10, lbl11, lbl12) and need to be able to access them programmatically to change the background color. In the example below, strLabel = "lbl01", which would correspond to the correct object in my form, but this cannot be passed as a string. Is there any way I could make this work?
Thanks!
private void btnTest_Click(object sender, EventArgs e)
{
TestHilight("0", "1");
}
public void TestHilight(string x, string y)
{
String strLabel = "lbl" + x + y;
strLabel.BackColor = System.Drawing.Color.Green;
}
It is better if you keep track of your Labels in memory, but if you want to find a Label or a control based on Name then you can use Control.Find method:
var control = this.Controls.Find(strLabel, true); //pass "lbl" + x + y;
if(control != null && control.OfType<Label>().Any())
{
//label found
Label label = control.OfType<Label>().First() as Label;
label.BackColor = System.Drawing.Color.Green;
}
You can shorten your code like:
public void TestHilight(string x, string y)
{
var matchedLabel = Controls.Find("lbl" + x + y, true).OfType<Label>().FirstOrDefault();
if (matchedLabel != null)
{
//label found
matchedLabel.BackColor = System.Drawing.Color.Green;
}
}
You can either maintain a reference to label controls in a Dictionary where the key would be the string e.g. lbl01 and when you need to set the BackColor, find the corresponding label from the Dictionary and set its property.
Alternatively, you can search for the control by its name and set its BackColor property
Related
I have a form written in c#, with various drop down lists, but I'm having problems with a listbox on the form. I need to populate a textbox with the values selected from the listbox when I double click on them. I've got the click event working, but the textbox will only populate with the object name, not the value from the listbox
i.e.
'System.Windows.Controls.SelectedItemCollection'
instead of the actual value.
Here is the entire code block I'm working on:
I should have just done this at the start - here is the complete code block I'm working on:
else if (theValue.FieldName.Equals("UIPathList", StringComparison.OrdinalIgnoreCase) == true)
{
int nRow = 14;
Button theUIPathOptionsButton = new Button();
TextBox theOldValueTextBox = AddLabelAndOldValue(theHelper, nRow, theValue);
theOldValueTextBox.Text = theValue.OldValue.Replace(",", "," + Environment.NewLine);
theUIPathOuterStackPanel = new StackPanel
{
Visibility = Visibility.Visible,
Orientation = Orientation.Vertical,
Background = new SolidColorBrush(Colors.White),
ClipToBounds = true,
};
theUIPathOptionsInnerStackPanel = new StackPanel
{
Visibility = Visibility.Visible,
Orientation = Orientation.Horizontal,
Background = new SolidColorBrush(Colors.White)
};
theUIPathOuterStackPanel.ClipToBounds = true;
TextBox theNewTextBox = new TextBox
{
TabIndex = nRow,
TextWrapping = TextWrapping.Wrap,
AcceptsReturn = true,
};
theNewTextBox.Clear();
theNewTextBox.MouseDoubleClick += MultiLineChildDatapointList_HandleMouseDoubleClick;
theNewTextBox.Focusable = true;
theNewTextBox.HorizontalAlignment = HorizontalAlignment.Stretch;
theNewTextBox.Width = 365;
theNewTextBox.PreviewKeyDown += theGetMetadataHelper.Preview_KeyDown_IsMultilineText;
theNewTextBox.Tag = theValue;
ListBox theUIPathOptionslistBox = new ListBox();
theUIPathOptionslistBox.Items.Add("RuntimeDefaults");
theUIPathOptionslistBox.Items.Add("CommonSettings");
theUIPathOptionslistBox.Items.Add(InputDatapointManager.CONST_CHANGE_RECORD_CHANGES_CLEAR_VALUE);
theUIPathOptionslistBox.TabIndex = nRow;
theUIPathOptionslistBox.SelectionMode = SelectionMode.Multiple;
theUIPathOptionslistBox.ClipToBounds = true;
theUIPathOptionslistBox.Focusable = true;
theUIPathOptionslistBox.Visibility = Visibility.Hidden;
theUIPathOptionslistBox.Height = 34;
theUIPathOptionsInnerStackPanel.Children.Add(theNewTextBox);
theUIPathOptionsInnerStackPanel.Children.Add(theUIPathOptionsButton);
theUIPathOuterStackPanel.Children.Add(theUIPathOptionsInnerStackPanel);
theUIPathOuterStackPanel.Children.Add(theUIPathOptionslistBox);
void button1_click(object sender, EventArgs e)
{
theUIPathOptionslistBox.Visibility = Visibility.Visible;
}
void button1_doubleclick(object sender, EventArgs e)
{
theNewTextBox.Text = theUIPathOptionslistBox.SelectedItem.ToString();
}
theUIPathOptionsButton.Click += button1_click;
theUIPathOptionslistBox.MouseDoubleClick += button1_doubleclick;
Grid.SetColumn(theUIPathOuterStackPanel, 4);
Grid.SetRow(theUIPathOuterStackPanel, nRow);
theDataGrid.Children.Add(theUIPathOuterStackPanel);
theEditControlList.Add(theNewTextBox);
}
This was (possibly) already answered here : Getting value of selected item in list box as string
string myItem = listBox1.GetItemText(listBox1.SelectedItem);
Then you just have to add your item to the textbox :
textBox1.Text = myItem;
If you don't want to create a new string variable, then this one is working too :
textBox1.Text = listBox1.SelectedItem.ToString();
ListBox, Item is a collection of objects, not strings, so you must let it know how to convert it to string, otherwise it will use its defualt .ToString() function that obviously the object currently in your items not giving the desired result.
Imagine items are oftype following class:
class SomeClass
{
public int Id;
public string Name;
}
You may do one of these three:
1.set the DisplayMember of your ListBox to Name
2.add override method to your class so that it overrides its .ToString() and return its Name property:
class SomeClass
{
public int Id;
public string Name;
public override string ToString()
{
return Name;
}
}
3.Just cast it to its real type and get the property you want:
SomeClass selected = (SomeClass)ListBox.SelectedItem;
TextBox1.Text = selected.Name;
This is because the TextBox will use the ToString() method on what it is bound to, which by default will return the class name.
You solutions are to either override the ToString() method of the class to return the value you want or set the text property of the TextBox to the text value you want rather then the object.
The solution I finally got to was as follows:
void theUIPathOptionslistBox_SelectedIndexChanged(object sender,
SelectionChangedEventArgs e)
{
theNewTextBox.Clear();
foreach (object selectedItem in theUIPathOptionslistBox.SelectedItems)
{
theNewTextBox.AppendText(selectedItem.ToString() + Environment.NewLine);
}
}
theUIPathOptionslistBox.SelectionChanged +=
theUIPathOptionslistBox_SelectedIndexChanged;
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've generated some textboxes and i want to the user input data in them after it added to form and then i use the data in them for some calculations.
how can i use the data?
TextBox t3 = new TextBox();
t3.Top = 222 + ((addalternativebutton - 3) * 60);
t3.Left = 214;
t3.Width = 76;
t3.Height = 22;
t3.Name = "txtwaste" + addalternativebutton.ToString();
this.tabore.Controls.Add(t3);
ww[addalternativebutton] = Convert.ToDouble(t3.Text);
As I mentioned in the comments you need to preserve the textbox instances which you are creating dynamically. You can either use generic dictionary, if you need to deal with the names assigned to them or you can use generic list.
Following solution I provide you which uses generic list.
First thing needed is a list which will preserve the textboxes.
public partial class Form1 : Form
{
private List<TextBox> textBoxes;
private int textBoxCount; //This is used to provide unique names to the
//textboxes and to track the number of dynamic textboxes.
public Form2()
{
InitializeComponent();
}
}
Now in click event of the button the textbox is created, positioned and added to the list as well as Form.Controls.
private void button1_Click(object sender, EventArgs e)
{
textBoxCount += 1;
TextBox t3 = new TextBox();
t3.Top = 20 + (22 * textBoxCount); //You can put your own logic to set the Top of textbox.
t3.Left = 120;
t3.Width = 50;
t3.Height = 20;
t3.Name = "txtwaste" + textBoxCount; //You can use your own logic of creating new name.
this.Controls.Add(t3);
this.textBoxes.Add(t3);
}
Now when you want to calculate the sum of the values of all the textboxes on click of another button.
private void button2_Click(object sender, EventArgs e)
{
double totalValue = 0;
foreach (var textBox in textBoxes)
{
double currentValue;
if (double.TryParse(textBox.Text, out currentValue))
{
totalValue += currentValue;
}
}
// Displaying totalValue in a label.
lblTotalValue.Text = "Total Value : " + totalValue;
}
This should help you resolve your issue.
Hey guys/girls I got myself stuck and I was hoping I could get some help with it. simply said I'm trying to make a soccerpool on windows form. Because the player can put in as many team's as he/she wants I put the code that makes the betting panels in a (for)loop with the text as 0. very handy if I say so myself but now I can't retrieve the correct input from the user or without breaking the loop. any idea's?
for (int i = 0; i < hometable.Rows.Count; i++)
{
DataRow dataRowHome = hometable.Rows[i];
DataRow dataRowAway = awayTable.Rows[i];
Label lblHomeTeam = new Label();
Label lblAwayTeam = new Label();
TextBox txtHomePred = new TextBox();
TextBox txtAwayPred = new TextBox();
lblHomeTeam.TextAlign = ContentAlignment.BottomRight;
lblHomeTeam.Text = dataRowHome["TeamName"].ToString();
lblHomeTeam.Location = new Point(15, txtHomePred.Bottom + (i * 30));
lblHomeTeam.AutoSize = true;
txtHomePred.Text = "0";
txtHomePred.Location = new Point(lblHomeTeam.Width, lblHomeTeam.Top - 3);
txtHomePred.Width = 40;
txtAwayPred.Text = "0";
txtAwayPred.Location = new Point(txtHomePred.Width + lblHomeTeam.Width, txtHomePred.Top);
txtAwayPred.Width = 40;
lblAwayTeam.Text = dataRowAway["TeamName"].ToString();
lblAwayTeam.Location = new Point(txtHomePred.Width + lblHomeTeam.Width + txtAwayPred.Width, txtHomePred.Top + 3);
lblAwayTeam.AutoSize = true;
pnlPredCard.Controls.Add(lblHomeTeam);
pnlPredCard.Controls.Add(txtHomePred);
pnlPredCard.Controls.Add(txtAwayPred);
pnlPredCard.Controls.Add(lblAwayTeam);
So what my end goal is, is recieving the input from the user validating them and then storing them in a database.
Well, depending on how the user activates an event that requires the reading of the TextBox you have a few possible solutions.
Here is one where the TextBox (read all TextBox's) waits for enter:
private void Form_Load(object sender, EventArgs e)
{
while(someLoop)
{
TextBox theTextBox = new TextBox();
theTextBox.Name = "SomeUniqeName";//Maybe team name?
theTextBox.KeyUp += TheTextBox_KeyUp;
}
}
private void TheTextBox_KeyUp(object sender, KeyEventArgs e)
{
if ( e.KeyCode == Keys.Enter )
{
TextBox textbox = (TextBox) sender;//Get the textbox
//Just an example
listOfTeams.First( r => r.TeamName == textbox.Name )
.SomeOtherProperty = textbox.Text;
}
}
The textbox's are now identifiable by their name and all have an event. No matter how many you make.
If you will store the data later with 1 click of a button (and another loop) this solution might be better:
string[] Teams = { "teamA", "teamB", "teamC" };
private void Form1_Load(object sender, EventArgs e)
{
for ( int i = 0; i < Teams.Length; i++ )
{
TextBox theTextBox = new TextBox();
//Prefix the name so we know this is a betting textbox
//Add the 'name' (teams[i] in this case) to find it
theTextBox.Name = "ThePrefix" + Teams[i];
}
}
private void someButton_Click(object sender, EventArgs e)
{
//We want all betting textbox's here but also by team name
for ( int i = 0; i < Teams.Length; i++ )
{
//Because we set the name, we can now find it with linq
TextBox textBox = (TextBox) this.Controls.Cast<Control>()
.FirstOrDefault( row => row.Name == "ThePrefix" + Teams[i] );
}
}
This way each textbox is identifiable and won't conflict with other textbox's (because of 'ThePrefix'). This is essentially the other way around from the first method as it looks for the textbox based on data rather than data based on textbox name.
I created an array of of TextBoxes and an array of Labels. When the information is updated in the TextBox I want it to change the Labels. How would I be able to do this? Below is piece of my code. I have not created the EvenHandler that I think is the part I need help with. All in C# using windows application form.
textBoxes = new TextBox[value];
labels = new Label[value];
for (int i = 1; i < value; i++)
{
textBoxes[i] = new TextBox();
textBoxes[i].Location = new Point(30, ToBox.Bottom + (i * 43));
labels[i] = new Label();
labels[i].Location = new Point(TopBox3[i].Width + 140, TopBox3[i].Top +3);
textboxes[i].ValueChanged += new EventHandler(this.TextBox_ValueChanged) ;
this.Controls.Add(labels[i]);
this.Controls.Add(textBoxes[i]);
}
You can remember the index of the TextBox in the Tag property
textBoxes[i].Tag = i;
and then use this value in your eventhandler to get the corresponding label (assuming that you hold the labels array as a local variable)
protected void TextBox_ValueChanged(object sender, EventArgs e)
{
TextBox textbox = sender as TextBox;
if(textbox==null)
return;
int index = Convert.ToInt32(textbox.Tag);
if(index >= 0 && index < this.labels.Length)
{
Label label = this.labels[index];
/* ... */
}
}
You should write something like this:
private void textBox1_ValueChanged(object sender, EventArgs e)
{
TextBox changedTxt = sender as TextBox;
for (int i = 1; i < value; i++)
if (textBoxes[i] == changedTxt)
{
Label lblToChange = labeld[i];
lblToChange.Text = changedTxt.Text;
break;
}
}
In the method the TextBox whose text has changed is passed as "sender". You look into your array for it, so you identify the index "i" which can be used to access the corresponding Label and to set its text.
BTW as Tim said, the event is TextChanged, not ValueChanged. Furthermore be aware that the event is triggered for every change in the text, i.e. as soon as you press a key the label will be updated. If you prefer to update your labels only when the user has finished to enter its text Leave is the event you should use.