0

Premise:- We have a list of key value pairs.

The Item count of this list will vary.

We have a form with a bunch of default buttons on it. (Edit - Built earlier in the designer, not at runtime.)

The buttons are named "button1, button2, ..."

We have more buttons than items in the list.

At runtime we want to transfer information from the list elements to the buttons and hide the unused buttons.

My question is how to address those buttons from withing a loop?

Using a for loop in VBA I could say this:-

Me.Controls("TB_Item" & Format(i, "00")).Visible = False

In C# I have this minimal example as a starting point (The form has 10 buttons):-

public UF_ButtonLoop()
    {
        InitializeComponent();

        List<KeyValuePair<string, string>> MyItems = new List<KeyValuePair<string, string>>
        {
            new KeyValuePair<string, string>("Apple", "Green Fruit"),
            new KeyValuePair<string, string>("Orange", "Orange Fruit"),
            new KeyValuePair<string, string>("Sprout", "Spawn of the Devil"),
            new KeyValuePair<string, string>("Hershey Bar", "A bit like chocolate"),
            new KeyValuePair<string, string>("Beefburger", "Man Food")
        };

        //Loop through the 10 buttons
        for (int i = 1; i < 11; i++)
        {
            if (i <= MyItems.Count )
            {
                //Transfer Data from list to button

                //Pseudo code
                Control("Button" + i).Text = (MyItems.ElementAt(i).Key);
                Control("Button" + i).Tag = (MyItems.ElementAt(i).Value);

            }
            else
            {
                //Hide the button as we've reached the end of the list so have no use for it.

                //Pseudo code
                Control("button" + 1).Hide();
            }

            // Note, VBA methos is:-
            // Me.Controls("TB_Item" & Format(i, "00")).Visible = False
        }

    }

Control("Button" + i) is not correct syntax.

Can I do this in C#, if so how?

If not what is the correct way?

Also I'm new here so if I'm asking things in the wrong way please don't be shy in telling me so!

Many thanks, Owen S.

6
  • 2
    Use "right control for the job" - DataGridView with one column of type DataGridViewButtonColumn. DataGridView provide possibility to create buttons from the list with dynamic amount of items in it. Commented Jan 29, 2020 at 9:18
  • Do you want to create new buttons in the loop and place them on the form? Commented Jan 29, 2020 at 9:27
  • are the buttons created in the designer? or do you create them at runtime? If they are created by the designer, then they will be in this.Controls.OfType<Button>(). Unless you have placed them into a sub container. Commented Jan 29, 2020 at 12:08
  • @Fabio Thanks for the suggestion, comments along the lines of "here's best practice for this scenario" are always welcome. Commented Jan 29, 2020 at 14:02
  • @MongZhu yes they were created in the designer. I've found a workaround I'll detail below for anyone searching in the future. Thanks for your comment. Commented Jan 29, 2020 at 14:03

2 Answers 2

1

Firstly thanks for the help, it's appreciated, especially the nudge towards doing it via other methods, or even different controls.

The answer to the question is probably split into two options:- (Answer 1) - Do it properly by creating just what you need at runtime, rather than using the static designer and then hiding what was over-built.

(Answer 2) - Quick "bodge" to get the code in my initial question working. (My C# experience can be measured in hours so I have plenty to learn but also need to get code working today for work...)

So one bodge method that works is to put the buttons in their own list and then reference that. Like so:-

public UF_ButtonLoop()
    {
        InitializeComponent();

        //TransferListToButtone_Rev1();
        List<KeyValuePair<string, string>> MyItems = new List<KeyValuePair<string, string>>
        {
            new KeyValuePair<string, string>("Apple", "Green Fruit"),
            new KeyValuePair<string, string>("Orange", "Orange Fruit"),
            new KeyValuePair<string, string>("Sprout", "Spawn of the Devil"),
            new KeyValuePair<string, string>("Hershey Bar", "A bit like chocolate"),
            new KeyValuePair<string, string>("Beefburger", "Man Food")
        };

        List<Control> ListOfButtons = new List<Control>
        {
            button1, button2, button3, button4, button5, button6, button7, button8, button9, button10
        };

        void A_Button_Click(object sender, System.EventArgs e)
        {      
            Console.WriteLine((sender as Button).Text + " = " + (sender as Button).Tag);
        }

        //Loop through the 10 buttons
        for (int i = 0; i < 10; i++)
        {
            if (i < MyItems.Count )
            {
                //Transfer Data from list to button
                    ListOfButtons.ElementAt(i).Text = (MyItems.ElementAt(i).Key);
                    ListOfButtons.ElementAt(i).Tag = (MyItems.ElementAt(i).Value);

                //Set Click Event
                    ListOfButtons.ElementAt(i).Click  += new EventHandler(A_Button_Click);
            }
            else
            {
                //Hide the button as we've reached the end of the list so have no use for it.
                    ListOfButtons.ElementAt(i).Hide();
            }

        }

    }

Cheers all, Owen S.

Sign up to request clarification or add additional context in comments.

Comments

0

I would recommend to create those buttons when you read the list. Do not create the buttons statically in designer. You need to create a List of buttons in the main Form and then add the buttons programmatically.

List creation

List<Button> buttons = new List<Button>(); 

Then in some loop where you go thru your data list

Button MyButton = new Button();
Mybutton.Location = new Point(YourX, YourY);
Mybutton.Text = "AnyText";
Mybutton.AutoSize = false;
MyButton.Size = new Size(width, height);
Mybutton.BackColor = Color.LightBlue;
Mybutton.Padding = new Padding(6);
buttons.add(MyButton);

Ad1. The best practice is to create your own "SpecialButton" class which is Inheritted from original Button class. Then you can add some special attributes to the button as is reference on some other element which should the SpecialButton control and etc...

1 Comment

Hi, and Thanks. Great info. and the example code is appreciated. I have some reading to do. Much obliged, Owen S.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.