C# - Use too many buttons as 1 variable - c#

I have a fairly simple question. I want to change the background color of 15 buttons,
but is is very cumbersome to write
button1.backgroundColor = Color.black
button2.backgroundColor = Color.black
.
.
.
How i can assign the color to all these buttons at once?
Like:
something allButtons = { button1.backgroundColor, button2.backgroundcolor .... }
I know how to do this in obj-c:
for (int i = 1; i < 16; i++)
{
UIButton *button = (UIButton *)[tag:i];
button.backgroundColor = [UIColor Color.black];
}
but how to accomplish this in C#?

You might be able to iterate through all the controls on the form, looking for buttons.
foreach (Control c in this.Controls)
{
if (c.GetType() == typeof(Button))
{
c.BackColor = Color.Black;
}
}

You put your buttons in an button array
Button[] buttons = new Button[] {button1, button2, .....};
Or in a List<Button>
List<Button> buttons = new List<Button>() { button1, button2, ....);
Next you loop over the button array or the List in the same way
foreach(Button btn in buttons)
btn.BackColor = Color.Black;
Another way to change this property is looping using the Forms.Controls container. But this will work only if the buttons are all contained in the Form.Controls collection.
foreach (Control btn in this.Controls.OfType<Button>())
{
btn.BackColor = Color.Black;
}
To fix the problem of buttons contained in inner ControlCollection you should use a recursive function that loops on every control container and reach buttons eventually inside that container
public void SetBackground(Control.ControlCollection coll)
{
foreach(Control ctr in coll)
{
if(ctr.Controls.Count > 0)
SetBackground(ctr.Controls);
else
{
Button btn = ctr as Button;
if(btn != null) btn.BackColor = Color.Black;
}
}
}
and call it from the toplevel collection
SetBackground(this.Controls);
It is a lot more complicated, so I prefer to use an array to explicitily declare the buttons that need to be changed.

Related

How to change the FlatStyle MouseDownBackColor of several buttons being in a WinForms Panel?

I need to parse controls in a panel to update some buttons.
I don't understand how to access this to change a buttons flat style mouse down back colour
public Color MouseDownBackColor {get; set;}
I know I can use this.button1.FlatAppearance.MouseDownBackColor = but in this case I have the button being accessed from a pannel as a var and it can't
be access it this way.
Update:
foreach (Control control in button_panel.Controls)
{
if (control is Button)
{
var button = (Button)control;
button.FlatAppearance.MouseOverBackColor = Color.FromArgb(0, 0, 0, 0);
}
}
The FlatStyle property of buttons must be set to FlatStyle.Flat to work.
You can use type casting (unboxing) towards Button after the type check:
foreach (Control control in button_panel.Controls)
{
if (control is Button)
{
var button = (Button)control;
button.FlatStyle = FlatStyle.Flat;
button.FlatAppearance.MouseDownBackColor = Color.Yellow;
}
}
You can also write this using Linq:
using System.Linq;
button_panel.Controls.OfType<Button>().ToList().ForEach(button =>
{
button.FlatStyle = FlatStyle.Flat;
button.FlatAppearance.MouseDownBackColor = Color.Yellow;
});

Strange Behavior of Form.Controls.OfType

I have a Form that gets built at run time where the user enters some data and either submits the data or cancels. The Form consists of a TableLayoutPanel with controls on it.
I add the Submit and Cancel buttons as follows.
TableLayoutPanel panel = new TableLayoutPanel
{
ColumnCount = 3,
RowCount = gridObj.ColList.Count() + 1,
Height = 800,
Width = 800
};
//other controls for user input...
Button submitButton = new Button();
submitButton.Text = "Submit";
submitButton.Click += (sender, EventArgs) => { SubmitClick(sender, EventArgs, gridObj); };
panel.Controls.Add(submitButton, 0, CurrentRow);
this.AcceptButton = (submitButton);
Button CancelButton = new Button();
CancelButton.Text = "Cancel";
panel.Controls.Add(CancelButton, 3, CurrentRow);
this.CancelButton = (CancelButton);
There is a case where it is necessary to remove the buttons from the form. I do so with the following code.
private void RemoveExistingButtons(TableLayoutPanel panel)
{
foreach (Control ctrl in panel.Controls.OfType<Button>())
{
panel.Controls.Remove(ctrl);
}
}
The way it looks to me this should find and remove each button from panel.
However it only removes the submit button.
The cancel button is not removed.
I was playing around with it and by adding another foreach, the cancel button gets removed by the second foreach.
private void RemoveExistingButtons(TableLayoutPanel panel)
{
foreach (Control ctrl in panel.Controls.OfType<Button>())
{
panel.Controls.Remove(ctrl);
}
foreach (Control ctrl in panel.Controls.OfType<Button>())
{
panel.Controls.Remove(ctrl);
}
}
I've tested this method with other control types, and they successfully remove multiple controls with only one loop, the way it 'should' work.
private void RemoveExistingControls(TableLayoutPanel panel)
{
foreach (Control ctrl in panel.Controls.OfType<Label>())
{
panel.Controls.Remove(ctrl);
}
foreach (Control ctrl in panel.Controls.OfType<TextBox>())
{
panel.Controls.Remove(ctrl);
}
}
I'm quite confused about this. Am I overlooking something simple?

C++-CLI Button Arrays to C# Button Arrays in Winforms

I am designing an application in C# Winforms (for the first time). I've designed several applications in C++ in the past, and am having difficulty converting some of my C++-CLI functions to C#.
I have 5 buttons along a side bar that toggles the visibility of the button's corresponding panel per button click. In order to do this, I set the visibility of all other panels to false. In order to achieve this in C++-CLI, I've done the following:
private: System::Void panels_Click(System::Object^ sender, System::EventArgs^ e) {
System::Windows::Forms::Button ^ currentbutton = (System::Windows::Forms::Button ^) sender;
array < Panel ^ > ^ objects = { panel1, panel2, panel3, panel4, panel5, panel6};
array < Button ^ > ^ buttons = { button1, button2, button3, button4, button5, button6 };
for (int i = 0; i < 6; i++) {
if (buttons[i]->Equals(currentbutton)) {
objects[i]->Visible = true;
}
else objects[i]->Visible = false;
}
}
The issue I am having is with the " array Panel ^" portion, as I can not find an equivalent in C#. Any help is appreciated.
Arrays are declared in C# using TypeName[].
Panel[] objects = { panel1, panel2, panel3, panel4, panel5, panel6 };
Button[] buttons = { button1, button2, button3, button4, button5, button6 };
You can cast the Controls collection to a List<Control>, and then access the control name for comparison. The Cast<T>() method is a linq extension method, so you'll have to add using System.Linq; to your namespace:
private void panels_Click(object sender, EventArgs e)
{
List<string> panelNames = new List<string>
{"panel1", "panel2", "panel3", "panel4", "panel5", "panel6"};
List<string> buttonNames = new List<string>
{"button1", "button2", "button3", "button4", "button5", "button6"};
List<Control> panels = this.Controls.Cast<Control>()
.Where(ctrl => panelNames.Contains(ctrl.Name)).ToList();
List<Control> buttons = this.Controls.Cast<Control>()
.Where(ctrl => buttonNames.Contains(ctrl.Name)).ToList();
Button thisButton = sender as Button;
for (int i = 0; i < buttons.Count; i++)
{
if (i < panels.Count) panels[i].Visible = buttons[i] == thisButton;
}
}

Set Properties via runtime for Multiple Controls

I have a form that contains about 25 Buttons. I want to set the same property for the Multiple buttons based on user input. The properties i want to change are,
Button text
Button Fore Color
Button Back Color
Button Size
I have been able to do this using code but the Code is long. I want to know if there is a way to loop to change all of them.
This is what i used
button1.Text = btntext;
button1.ForeColor = btnforecolor;
button1.BackColor = btnbackcolor;
button1.Size = new Size(btnwidth, btnheight);
I had to do this like this for the 25 button, i want to know if there is any better way to do this with less code??..
Any suggestion will be appreciated.
Two options here:
1) Create a list of buttons and loop:
for (int i = 0; i < 25; i++){
Button btn = new Button();
btn.Text = ...
btn.Location = new Point(10 + (i%5)*100, (i/5)*30);
btn.Click += new EventHandler(btn_Click); // TODO: Implement btn_Click event
this.Controls.Add(btn);
}
2) Loop through your existing controls:
foreach (Control c in this.Controls) {
Button btn = c as Button;
if (btn == null) continue;
btn.Text = ...
}
If you can't iterate through all of the buttons on a form but need a specific list of buttons I use this code.
List<Button> ListOfButtons = new List<Button>
{
this.Button1,
this.Button2,
}
foreach (Button myButton in ListOfButtons)
{
//Do your assigments to myButton
}

How to change properties of a Control that is in List<UIControl> without using Loop?

I have the following code where a click event will dynamically create additional Canvas to the WrapPanel, and each Canvas contains a TextBox and a Button. Once the Button on one Canvas is click, TextBox.Text and Button.Content change from "Foo" to "Jesus".
The below code works, but it's not ideal. Because each property Change ("Foo" to "Jesus), I have to run a loop. I have to run two loops just to change the text on the TextBox and Button. Is there a direct way to change the Properties other then a Loop? My actually application contains 30+ controls in a Canvas, I don't want to run 30+ loops each time just to change some text.
List<Canvas> cvList = new List<Canvas>();
List<TextBox> tbList = new List<TextBox>();
List<Button> FooList = new List<Button>();
WrapPanel wp = new WrapPanel();
private void createbtn1_Click(object sender, RoutedEventArgs e)
{
Canvas cv = new Canvas();
StackPanel sp = new StackPanel();
TextBox tb = new TextBox();
Button Foo = new Button();
sp.Orientation = Orientation.Vertical;
sp.Children.Add(tb);
sp.Children.Add(Foo);
cv.Children.Add(sp);
wp.Children.Add(cv);
cvList.Add(cv);
tbList.Add(tb);
FooList.Add(Foo);
cv.Width = 100;
cv.Height = 100;
tb.Text = "#" + (cvList.IndexOf(cv)+1);
tb.Width = 50;
tb.Height = 30;
Foo.Content = "Foo";
Foo.Click += destroy_Click;
}
private void Foo_Click(object sender, RoutedEventArgs e)
{
Button b = sender as Button;
var bIndex = FooList.IndexOf(b);
foreach (TextBox t in tbList)
{
if (tbList.IndexOf(t) == bIndex)
{
t.Text = "Jesus";
}
}
foreach (Button f in FooList)
{
if (FooList.IndexOf(t) == bIndex)
{
t.Content = "Jesus";
}
}
}
Just access the text boxes by index and set the content of the button directly:
if(bIndex < tbList.Count && bIndex != -1)
tbList[bIndex].Text = "Jesus";
if(b != null && bIndex != -1)
b.Content = "Jesus";
why can't you just get the item at the index and set that items text:
tbList[bindex].Text="Jesus";
As for setting the buttons content, you already have the button from the click event, so just use that:
b.Content = "Jesus";
You current code just loops through each item in the list and gets the index of the item and sees if it is the index you want. Accessing by the indexer of the list directly will give you what you want.
You will probably want to do some error checking, but that is not currently done in your existing code either.
Some info on using indexers from MSDN

Categories