0

I have function which add colors to color palette. The code below is working but it is dirty. I want to add a counter named x and use it like

btnSpecialColor$(x)

Is there any way to do this?

 if (btnSpecialColor1.BackColor == Color.White)
                btnSpecialColor1.BackColor = colorDialog1.Color;
            else if (btnSpecialColor2.BackColor == Color.White)
                btnSpecialColor2.BackColor = colorDialog1.Color;
            else if (btnSpecialColor3.BackColor == Color.White)
                btnSpecialColor3.BackColor = colorDialog1.Color;
            else if (btnSpecialColor4.BackColor == Color.White)
                btnSpecialColor4.BackColor = colorDialog1.Color;
            else if (btnSpecialColor5.BackColor == Color.White)
                btnSpecialColor5.BackColor = colorDialog1.Color;
            else if (btnSpecialColor6.BackColor == Color.White)
                btnSpecialColor6.BackColor = colorDialog1.Color;
            else if (btnSpecialColor7.BackColor == Color.White)
                btnSpecialColor7.BackColor = colorDialog1.Color;
            else if (btnSpecialColor8.BackColor == Color.White)
                btnSpecialColor8.BackColor = colorDialog1.Color;
            else if (btnSpecialColor9.BackColor == Color.White)
                btnSpecialColor9.BackColor = colorDialog1.Color;
            else if (btnSpecialColor10.BackColor == Color.White)
                btnSpecialColor10.BackColor = colorDialog1.Color;
        }

2 Answers2

4

If all the buttons are named using the pattern indicated by your code and the test condition chain is as is, you can use Linq like this:

using System.Linq;

var found = Controls.OfType<Button>()
                    .Where(button => button.Name.StartsWith("btnSpecialColor"))
                    .Where(button => button.BackColor == Color.White)
                    .OrderBy(button => button.Name.Length)
                    .ThenBy(button => button.Name)
                    .FirstOrDefault();

if ( found != null )
  found.BackColor = colorDialog1.Color;

We select all buttons of the form at its root level and we filter by the name and the color and we order by name numerically to take the first and change the color if not null.

If buttons are in a panel, use:

var found = MyPanel.Controls...

Also you can compare strings case insensitive to avoid some mistakes:

StartsWith("...", StringComparison.OrdinalIgnoreCase)

If you need to recursively parse all containers and subcontainers of the form, you can take a look at:

How to change BackColor of all my Panel in my Form

How to toggle visibility in Windows Forms C#

  • 2
    The given code is not an equivalent. It changes the color of all buttons, not only the first. Note that you also need to sort it by the number with extra difficulty that `10` comes after `9` – Thomas Weller Jan 04 '21 at 12:25
  • 1
    @ThomasWeller Indeed. Question checked and answer updated, thanks! –  Jan 04 '21 at 12:27
  • Thanks for answer. It seems to should work. But found is always null. When delete the if block, throws null error every time. The buttons are in a tabpage, I try "var found = TabPage1.Controls..." but still not working – Bedirhan Gökce Jan 04 '21 at 12:58
  • 1
    @BedirhanGökce This should work, I checked it works even in a tabpage. No doubt a trifle. Can you download a zip of your project somewhere and provide a link, please? It will be the easiest and quickest way. –  Jan 04 '21 at 13:05
  • 1
    @OlivierRogier https://wetransfer.com/downloads/dbccde078446234630e3d668d465910720210104131214/fe7322 Sorry for size of project. This is group project and I try to fix something. Just form1 class had 950 lines of code and I tried to reduce this. Program works but designer throw error rihgt now because of my eventhandler. – Bedirhan Gökce Jan 04 '21 at 13:25
  • 1
    @BedirhanGökce I can't open the form in the visual studio form designer that shows exceptions. And if I run the app I see nothing but a top menu: the workspace is blank. But in the code I see that buttons are in a groupbox so you need to write: `groupBox1.Controls.OfType...`. After that I see that works: clicking in the `Edit Colors` control put me on the breakpoint and found is not null and a sqare is changed, one after one from left to right in the bottom line. So this may help you to advance in the project. –  Jan 04 '21 at 13:32
  • 1
    @OlivierRogier thanks for helping. It worked exactly as I want. If you couldn't see color palette, it will be visible by clicking pen. And I have last issue about that designer error, do you have any solution for that? As I said line with the "new event handler" is working well but designer throws error – Bedirhan Gökce Jan 04 '21 at 13:47
  • 1
    @BedirhanGökce I saw events are assigned to lambdas, which is not the standard of the visual studio form designer nor compatible: `this.btnYellow.Click + = new System.EventHandler((sender, e) => MyButtonClick(sender, e, btnYellow));`. I have never seen this (until VS2017) and only you know what it is from. It should look like `this.btnYellow.Click + = new System.EventHandler (this.btnYellow_Click);`. The solution is to remove all event lines from the designer generated file and recreate them using the designer). But there is a third parameter and it should be for a goal that you will mimic. –  Jan 04 '21 at 13:51
0

The solution from Olivier Rogier should work fine but I have another solution using a List<Button>.

//Create list of buttons
List<Button> buttons = new List<Button>(Controls.OfType<Button>());

//Check each button
foreach(Button button in buttons)
{
    //if BackColor is White..
    if(button.BackColor == Color.White)
    {
        //Change BackColor and stop check
        button.BackColor = colorDialog1.Color;
        break;
    }
}

In my opinion this is a cleaner solution but there is a bit of a catch.

This solution will check all buttons inside your view! This is a good thing if there are no other buttons since the names of your buttons become irrelevant.

But if there are other buttons which you don't want to check you should change the List to this:

//Create list of buttons
List<Button> buttons = new List<Button>(Controls.OfType<Button>().Where(button => button.Name.StartsWith("btnSpecialColor")));
Ottxr
  • 153
  • 3
  • 13