I descripted my problem in script comments. Function GraphicClassStructure is only for create buttons and label. But mainly function is plusButton_click. I need that if i clicked on first plus button so i need change text for first added label.
Script: (Problem is here: plusButton_click, i descripted problem to case)
class GraphicClassStructure : GraphicPosition
{
// Button
public Button plus;
public PictureBox classBackround = new PictureBox();
// Label
Label points;
public void CreateSpellsButton()
{
for (int j = 0; j < 3; j++)
{
for (int i = 0; i < 10; i++)
{
plus = new Button();
points = new Label();
switch (j)
{
case 0:
points.Location = Location[1][i];
points.Location = new Point(points.Location.X + 8, points.Location.Y + 45);
plus.Location = Location[2][i];
break;
case 1:
plus.Location = Location[2][i];
plus.Location = new Point(plus.Location.X + 205, plus.Location.Y);
points.Location = Location[1][i];
points.Location = new Point(points.Location.X + 213, points.Location.Y + 45);
break;
case 2:
plus.Location = Location[2][i];
plus.Location = new Point(plus.Location.X + 410, plus.Location.Y);
points.Location = Location[1][i];
points.Location = new Point(points.Location.X + 418, points.Location.Y + 45);
break;
}
// Labels for point
points.BackColor = Color.Transparent;
points.ForeColor = Color.FromArgb(((int)(((byte)(193)))), ((int)(((byte)(196)))), ((int)(((byte)(181)))));
points.BackgroundImageLayout = ImageLayout.Stretch;
points.FlatStyle = FlatStyle.Flat;
points.Name = "points";
points.Name = spells.Name + i.ToString() + "_" + j.ToString();
if (i >= 6)
points.Text = "0 / 2";
else
points.Text = "0 / 1";
points.VisibleChanged += new EventHandler(classUniqueButtons_VisibleChanged);
// Plus
plus.BackColor = Color.Transparent;
plus.BackgroundImage = BuildResource.plus;
plus.BackgroundImageLayout = ImageLayout.Stretch;
plus.FlatAppearance.BorderSize = 0;
plus.FlatAppearance.MouseDownBackColor = Color.Transparent;
plus.FlatAppearance.MouseOverBackColor = Color.Transparent;
plus.FlatStyle = FlatStyle.Flat;
plus.Name = "plus";
plus.Size = Size[0][9];
plus.UseVisualStyleBackColor = false;
plus.Name = plus.Name + i.ToString() + "_" + j.ToString();
plus.Click += new EventHandler(plusButton_click);
plus.VisibleChanged += new EventHandler(classUniqueButtons_VisibleChanged);
plus.MouseEnter += new EventHandler(this.classButton_MouseEnter);
plus.MouseLeave += new EventHandler(this.classButton_MouseLeave);
classBackround.Controls.Add(plus);
classBackround.Controls.Add(points);
}
}
}
private void plusButton_click(object sender, EventArgs e)
{
var currentButton = sender as Button;
var name = currentButton.Name;
switch (name)
{
// Ultimate
case "plus0_0":
// If i clicked on this button so i need change text for first added label
// I try this, but it changed only last added labe
points.Text = "test";
break;
case "plus0_1":
// If i clicked on this button so i need change text for second added label
break;
}
}
private void minusButton_click(object sender, EventArgs e)
{
var currentButton = sender as Button;
var name = currentButton.Name;
switch (name)
{
// Ultimate
case "minus0_0":
// If i clicked on this button so i need change text for first added label
// I try this, but it changed only last added labe
points.Text = "test";
break;
case "minus0_1":
// If i clicked on this button so i need change text for second added label
break;
}
}
}
very simple to do here what you need
for (int j = 0; j < 3; j++)
{
for (int i = 0; i < 10; i++)
{
plus = new Button();
//tag is an object and can be used to reference any other object
plus.Tag = new Label();
and to retrieve what you need do this
private void plusButton_click(object sender, EventArgs e)
{
var currentButton = sender as Button;
var name = currentButton.Name;
switch (name)
{
// Ultimate
case "plus0_0":
(currentButton.Tag as Label).Text = "test";
break;
case "plus0_1":
(currentButton.Tag as Label).Text ="test2"
break;
}
}
You are using a global reference to the label which you have overwritten in each iteration of your loop. Therefore it always references the last label. Since you always add the label after the button and have the reference to the button you can probably get the correct label like this:
Label pointsLabel = (Label)classBackround.Controls[classBackround.Controls.IndexOf(currentButton) + 1]
Related
I wanna change the Text properties of Label using Buttons just like in hangman; but after I created the Label, I became confused when I try to access the specific Label
// creating label
for (int i = 0; i < numericUpDown1.Value; i++)
{
Label l = new Label();
l.Text = "_";
l.Width = 20;
l.Height = 25;
l.Left = i * 20 + 510;
l.Top = 20;
l.BackColor = Color.Transparent;
groupBox2.Controls.Add(l);
}
// function to change the label text
// if I clicked the button
// the first label text will be changed to the text in the button i clicked
private void B_Click(object sender, EventArgs e)
{
var thsBtn = (Button)sender;
bool benar = false;
if (benar == false)
{
thsBtn.Text = " ";
thsBtn.Enabled = false;
}
else
{
thsBtn.Enabled = false;
}
}
You can organize created Labels into a collection, say, List<Label>:
private List<Label> m_CreatedLabels = new List<Label>();
...
// Remove all previous labels
foreach (Label lbl in m_CreatedLabels)
lbl.Dispose();
m_CreatedLabels.Clear();
// Create new ones
for (int i = 0; i < numericUpDown1.Value; i++) {
m_CreatedLabels.Add(new Label() {
Text = "_",
Width = 20,
Height = 25,
Left = i * 20 + 510,
Top = 20,
BackColor = Color.Transparent,
Parent = groupBox2
});
}
Now you have m_CreatedLabels collection to work with created Labels, e.g.
private void B_Click(object sender, EventArgs e) {
var thsBtn = sender as Button;
// you may want to add a condition into FirstOrDefault(), e.g.
// .FirstOrDefault(lbl => lbl.Text == "_")
// - first label with "_" Text
Label lblToProcess = m_CreatedLabels
.FirstOrDefault();
if (null != lblToProcess)
lblToProcess.Text = thsBtn.Text;
thsBtn.Enabled = false;
}
One option here is to give your dynamically created Label instances a Name. From there, you should be able to use ControlCollection.Find to find your Label instances by name.
private void CreateLabels()
{
for (int i = 0; i < numericUpDown1.Value; i++)
{
Label l = new Label();
l.Name = $"DynamicLabel{i}";
l.Text = "_";
l.Width = 20;
l.Height = 25;
l.Left = i * 20 + 510;
l.Top = 20;
l.BackColor = Color.Transparent;
groupBox2.Controls.Add(l);
}
}
private void DoSomethingWithADynamicLabel(int dynamicLabelIndex)
{
Label l = groupBox2.Controls.Find($"DynamicLabel{i}", true).FirstOrDefault() as Label;
if (l is null)
{
// Couldn't find the label...
return;
}
// Do something with l
}
When creating the Label instances inside CreateLabels, I'm simply appending the for loop's counter to the string "DynamicLabel". This gives you a bunch of Labels with names like "DynamicLabel0", "DynamicLable1", "DynamicLabel2", etc...
Then in DoSomethingWithADynamicLabel, assuming you have the index of the Label you want to deal with, you can use groupBox2.Controls.Find to actually find the Label you're interested in. ControlCollection.Find returns Control[], so calling FirstOrDefault will take the first item from the array or null if no Control with the given name exists.
I have a bit of an issue here.
I'm trying to create dynamic clickevents with variable data.
for(int i = 0; i < data.Devices.Length; i++)
{
Button _button = new Button();
_button.Size = new Size(100, 15);
_button.Text = data.Devices[i].Alias;
_button.Name = "textbox" + i.ToString();
_button.Location = new Point(x,y);
x += 110;
if(x > 1850)
{
y += 50;
x = 10;
}
if (data.Devices[i].OnlineState == "Online")
{
_button.BackColor = Color.Green;
}
else
{
_button.BackColor = Color.Red;
}
_button.Click += (Sender, args) =>
{
MessageBox.Show(data.Devices[i].Alias);
};
Controls.Add(_button);
}
The idea here is that I'll create buttons until length of the list is done (The list and position of these objects vary).
What I'm looking for is to make a bunch of buttons, and when you click on the button there should you'll open another screen with some statistics attached to that object.
Since the data will vary A LOT there is no way to hardcode each scenario, but instead I'm looking to do the same thing as you can do in Android, see below.
for (int i = 1; i <= 20; i++) {
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
Button btn = new Button(this);
btn.setId(i);
final int id_ = btn.getId();
btn.setText("button " + id_);
btn.setBackgroundColor(Color.rgb(70, 80, 90));
linear.addView(btn, params);
btn1 = ((Button) findViewById(id_));
btn1.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Toast.makeText(view.getContext(), "Button clicked index = " + id_, Toast.LENGTH_SHORT).show();
}
});
Is there any way I can achieve this?
Kind Regards.
I think the problem you are experiencing is regarding closures.
In your example you are adding the event handler with a delegate that's referencing the variable i which changes each loop iteration. So when the event handler is actually executed (when the button is clicked) i is out of scope.
You could do something like this:
private void Form1_Shown(object sender, EventArgs e)
{
var items = new[] { "Item One", "Item Two", "Item Three", "Item Four", "Item Five" };
for (int i = 0; i < items.Length; i++)
{
var btn = new Button
{
Text = $"Button {i + 1}",
Tag = items[i]
};
btn.Click += (object obj, EventArgs args)
=>
{
MessageBox.Show($"Hello. {((Button)obj).Tag}");
};
flowLayoutPanel1.Controls.Add(btn);
}
}
In your case - the button's tag can be set to data.Devices[i] - in other words it doesn't have to be a string it can be an object.
I start off by creating the buttons with the and placing them on the screen.
for (int i = 0; i < data.Devices.Length; i++){
Button _button = new Button();
_button.Size = new System.Drawing.Size(100, 55);
_button.Text = data.Devices[i].Alias;
_button.Name = "dynamicButton";
_button.FlatStyle = FlatStyle.Flat;
_button.Tag = data.Devices[i].Alias + "|" +
data.Devices[i].DeviceId + "|" +
data.Devices[i].LastSeen + "|" +
data.Devices[i].OnlineState + "|" +
data.Devices[i].Description + "|" +
data.Devices[i].RemotecontrolId;
_button.Location = new System.Drawing.Point(x, y);
x += 110;
if (x > 1850)
{
y += 60;
x = 30;
}
_button.Click += new EventHandler(bt_click);
Controls.Add(_button);
}
And then using the onclick event.
protected void bt_click(object sender, EventArgs e)
{
Button btn = sender as Button;
String[] information = btn.Tag.ToString().Split('|');
String present = "Namn: " + information[0]
+ "\nDeviceID: " + information[1]
+ "\nSenast uppe: " + information[2]
+ "\nStatus: " + information[3]
+ "\nEmail: " + information[4]
+ "\nTW-ID: " + information[5];
MessageBox.Show(present);
//DO THE THINGS WITH THE INFORMATION
}
And then to unload everything and eventually updating the status of the device.
for (int i = 0; i < 10; i++)
{
foreach (Control item in Controls.OfType<Control>())
{
if (item.Name == "dynamicButton")
{
Controls.Remove(item);
}
}
}
For some reason I have to loop that thing a couple of times, beacuse it won't delete them all, but instead deleting them in some pattern.
(only takes every other one each time)
I looped it 10 times for good measures.
It does exactly what I want it to do, and new devices gets added automaticly and removed devices dissapears just as fast.
How to get value of checkboxes (and the textbox upon change in text) in real time with form particulars that are all generated via code?
This following code produces a form upon button press, the form has checkboxes and a richtextbox. Ideally I want any interaction to have an effect, so if I paste in a grid of ones and zeros the checkboxes update, and once a checkbox gets click, the corresponding one or zero in the textarea will update (So that I can then copy the grid (matrix) out and into another program.
I know how to get the events using the visual studio GUI maker, but not from a programmatically created form like this.
private void begin_button_Click(object sender, EventArgs e)
{
// Build the child form
Form check_box = new Form();
check_box.FormBorderStyle = FormBorderStyle.FixedSingle;
// Get the values from the textboxes
int height = Convert.ToInt16(this.height_input.Text);
int width = Convert.ToInt16(this.width_input.Text);
// Set the dimensions of the form
check_box.Width = width * 15 + 40;
check_box.Height = ( height * 15 + 40 ) * 3;
// Build checkboxes for the checkbox form
CheckBox[] chk;
chk = new CheckBox[height * width];
int count = 0;
for (int i = 1; i <= height; i++)
{
for (int j = 1; j <= width; j++)
{
chk[count] = new CheckBox();
chk[count].Name = count.ToString();
chk[count].Width = 15; // because the default is 100px for text
chk[count].Height = 15;
chk[count].Location = new Point(j * 15, i * 15);
chk[count].CheckedChanged += new EventHandler(this.CheckedChanged);
check_box.Controls.Add(chk[count]);
count += 1;
//Console.WriteLine(" i: " + i + " j: " + j + " Count: " + count);
}
}
RichTextBox output_area;
output_area = new RichTextBox();
output_area.Location = new Point(chk[0].Location.X, chk[count-1].Location.Y + 30);
check_box.Controls.Add(output_area);
output_area.Text = "hello world\n1,1,1,1,1,1,1,1,1\n0,0,0,0,0,1,0,1\nthese ones and zeros are meant to update in real time!";
output_area.Width = check_box.Width - 40;
output_area.Height = check_box.Height / 2;
// Run the form
check_box.ShowDialog();
}
EDIT:
I have added the event handler and it's working, however I can't access the checkbox form, only the main form.
private void CheckedChanged(object sender, EventArgs e)
{
//throw new NotImplementedException();
CheckBox x = (CheckBox)sender;
Console.WriteLine(x);
Console.WriteLine(x.Name.ToString());
}
Have a look at the .Designer file that the form designer generates for you!
Anyway, in your loop, try something like this:
chk[count].CheckedChanged += MyFancyHandler;
And the handler itself will look just like a normal handler:
private void MyFancyHandler( object sender, EventArgs e )
{
// ...
}
Also notice that the sender argument there will contain a reference to whichever checkbox/control the event refers to.
Below code updates matrix text in the rich text box when check box check state changed.
RichTextBox output_area;
CheckBox[] chk;
Size MatrixSize;
private void begin_button_Click()
{
// Build the child form
Form check_box = new Form();
check_box.FormBorderStyle = FormBorderStyle.FixedSingle;
check_box.StartPosition = FormStartPosition.CenterScreen;
// Get the values from the textboxes
int height = Convert.ToInt16("10");
int width = Convert.ToInt16("7");
MatrixSize = new Size(width, height);
// Set the dimensions of the form
check_box.Width = width * 15 + 40;
check_box.Height = (height * 15 + 40) * 3;
// Build checkboxes for the checkbox form
chk = new CheckBox[height * width];
int count = 0;
for (int i = 1; i <= height; i++)
{
for (int j = 1; j <= width; j++)
{
chk[count] = new CheckBox();
chk[count].Name = count.ToString();
chk[count].Width = 15; // because the default is 100px for text
chk[count].Height = 15;
chk[count].Location = new Point(j * 15, i * 15);
check_box.Controls.Add(chk[count]);
chk[count].CheckedChanged += new EventHandler(CheckBox1_CheckedChanged);
count += 1;
//Console.WriteLine(" i: " + i + " j: " + j + " Count: " + count);
}
}
output_area = new RichTextBox();
output_area.Location = new Point(chk[0].Location.X, chk[count - 1].Location.Y + 30);
check_box.Controls.Add(output_area);
output_area.Text = "hello world\n1,1,1,1,1,1,1,1,1\n0,0,0,0,0,1,0,1\nthese ones and zeros are meant to update in real time!";
output_area.Width = check_box.Width - 40;
output_area.Height = check_box.Height / 2;
// Run the form
check_box.ShowDialog();
}
private void CheckBox1_CheckedChanged(Object sender, EventArgs e)
{
CheckBox c = (CheckBox)sender;
Debug.WriteLine(c.Name);
StringBuilder sb = new StringBuilder();
int count = 0;
for (int i = 1; i <= MatrixSize.Height; i++)
{
for (int j = 1; j <= MatrixSize.Width; j++)
{
if (chk[count].Checked)
{
sb.Append("1,");
}
else
{
sb.Append("0,");
}
count += 1;
}
sb.Append("\r\n");
}
output_area.Text = sb.ToString();
}
on startup I'm generating a lot of controls 90 to be exact and everything is working ok EXCEPT for the labels they are not being drawn or something? they are there because I can click them and they show proper ID (click event) here's the genereation code
private static bool ClientsLoaded = false;
private static WebBrowser[] Clients = new WebBrowser[45];
private static Label[] ClientLabel = new Label[45];
private static int MaximizedClient = -1;
public Form1()
{
InitializeComponent();
int WBoffsetX = 0;
int WBoffsetY = 0;
int lbloffsetX = 0;
int lbloffsetY = 0;
for (int i = 0; i < 45; i++)
{
var wb = new WebBrowser();
Clients[i] = wb;
wb.ScrollBarsEnabled = false;
wb.Height = 12;
wb.Width = 12;
wb.Location = new Point(2 + WBoffsetX, 2 + WBoffsetY);
WBoffsetX += 13;
wb.ScriptErrorsSuppressed = true;
this.Controls.Add(wb);
ClientLabel[i] = new Label();
ClientLabel[i].Name = "lbl_" + i;
ClientLabel[i].Font = new Font("Arial", 12);
ClientLabel[i].ForeColor = System.Drawing.Color.White;
ClientLabel[i].Location = new Point(12 + lbloffsetX, 450 + lbloffsetY);
lbloffsetX += 22;
ClientLabel[i].Click += new EventHandler(lbl_click);
ClientLabel[i].Text = "C" + i + ": o";
this.Controls.Add(ClientLabel[i]);
}
}
I've tried adding a button with for(45) clientlabel[i].Refresh() and it did nothing I tried changing the visibilty of them all to false and then back to true and nothing however I did find 1 thing interesting if I hide lbl_1 label 2 text will appear if I had label 2 label 3 text will appear but if I change the previous label back to visible they stay invisible textwise
I can click in a line on the form and
private void lbl_click(object sender, EventArgs e)
{
int id = -1;
var s = sender.ToString();
for(int i = 0; i<=45; i++)
{
if (s.Contains("C" + i + ":"))
{
id = i;
}
}
MessageBox.Show("Hello label, " + id);
}
will pop up the proper ids etc
does anyone know what's causing this maybe? or how to fix it
Well, I don't know what is the problem. This code works well enough and it has only marginal differences with the original(AutoSize property, explicit statement of Height and Width, and minor Location adjustment):
for (int i = 0; i < ClientLabel.Length; i++)
{
// Web browsers
WebBrowser wb = new WebBrowser()
{
ScrollBarsEnabled = false,
Height = 12,
Width = 12,
Location = new Point(2 + WBoffsetX, 2 + WBoffsetY),
ScriptErrorsSuppressed = true
};
WBoffsetX += 13;
Clients[i] = wb;
// Labels
Label label = new Label()
{
Name = "label_" + i,
Text = "Data",
AutoSize = true,
Location = new Point(50 + lbloffsetX, 50 + lbloffsetY),
Width = 100,
Height = 20,
Font = new Font("Arial", 12),
ForeColor = System.Drawing.Color.White,
};
label.Click += new EventHandler(lbl_click);
ClientLabel[i] = label;
lbloffsetX += 30;
}
this.Controls.AddRange(Clients);
this.Controls.AddRange(ClientLabel);
I want to create 10 buttons on my form when I click on button1. No error with this code below but it doesnt work either.
private void button1_Click(object sender, EventArgs e)
{
List<Button> buttons = new List<Button>();
for (int i = 0; i < buttons.Capacity; i++)
{
this.Controls.Add(buttons[i]);
}
}
You aren't creating any buttons, you just have an empty list.
You can forget the list and just create the buttons in the loop.
private void button1_Click(object sender, EventArgs e)
{
int top = 50;
int left = 100;
for (int i = 0; i < 10; i++)
{
Button button = new Button();
button.Left = left;
button.Top = top;
this.Controls.Add(button);
top += button.Height + 2;
}
}
It doesn't work because the list is empty. Try this:
private void button1_Click(object sender, EventArgs e)
{
List<Button> buttons = new List<Button>();
for (int i = 0; i < 10; i++)
{
Button newButton = new Button();
buttons.Add(newButton);
this.Controls.Add(newButton);
}
}
You could do something like this:
Point newLoc = new Point(5,5); // Set whatever you want for initial location
for(int i=0; i < 10; ++i)
{
Button b = new Button();
b.Size = new Size(10, 50);
b.Location = newLoc;
newLoc.Offset(0, b.Height + 5);
Controls.Add(b);
}
If you want them to layout in any sort of reasonable fashion it would be better to add them to one of the layout panels (i.e. FlowLayoutPanel) or to align them yourself.
Two problems- List is empty. You need to add some buttons to the list first. Second problem: You can't add buttons to "this". "This" is not referencing what you think, I think. Change this to reference a Panel for instance.
//Assume you have on your .aspx page:
<asp:Panel ID="Panel_Controls" runat="server"></asp:Panel>
private void button1_Click(object sender, EventArgs e)
{
List<Button> buttons = new List<Button>();
for (int i = 0; i < buttons.Capacity; i++)
{
Panel_Controls.Controls.Add(buttons[i]);
}
}
use button array like this.it will create 3 dynamic buttons bcoz h variable has value of 3
private void button1_Click(object sender, EventArgs e)
{
int h =3;
Button[] buttonArray = new Button[8];
for (int i = 0; i <= h-1; i++)
{
buttonArray[i] = new Button();
buttonArray[i].Size = new Size(20, 43);
buttonArray[i].Name= ""+i+"";
buttonArray[i].Click += button_Click;//function
buttonArray[i].Location = new Point(40, 20 + (i * 20));
panel1.Controls.Add(buttonArray[i]);
} }
I had the same doubt and came up with the following contribution:
int height = this.Size.Height;
int width = this.Size.Width;
int widthOffset = 10;
int heightOffset = 10;
int btnWidth = 100; // Button Widht
int btnHeight = 40; // Button Height
for (int i = 0; i < 50; ++i)
{
if ((widthOffset + btnWidth) >= width)
{
widthOffset = 10;
heightOffset = heightOffset + btnHeight
var button = new Button();
button.Size = new Size(btnWidth, btnHeight);
button.Name = "" + i + "";
button.Text = "" + i + "";
//button.Click += button_Click; // Button Click Event
button.Location = new Point(widthOffset, heightOffset);
Controls.Add(button);
widthOffset = widthOffset + (btnWidth);
}
else
{
var button = new Button();
button.Size = new Size(btnWidth, btnHeight);
button.Name = "" + i + "";
button.Text = "" + i + "";
//button.Click += button_Click; // Button Click Event
button.Location = new Point(widthOffset, heightOffset);
Controls.Add(button);
widthOffset = widthOffset + (btnWidth);
}
}
Expected Behaviour:
This will generate the buttons dinamically and using the current window size, "break a line" when the button exceeds the right margin of your window.
First, you aren't actually creating 10 buttons. Second, you need to set the location of each button, or they will appear on top of each other. This will do the trick:
for (int i = 0; i < 10; ++i)
{
var button = new Button();
button.Location = new Point(button.Width * i + 4, 0);
Controls.Add(button);
}
You can't add a Button to an empty list without creating a new instance of that Button.
You are missing the
Button newButton = new Button();
in your code plus get rid of the .Capacity