1

I have different objects: 6 buttons, Listbox, and 5 labels, those names are like lblHum, lblCo2...

I need to show or hide them together with one button click.

Is it possible (without putting objects in a panel or group boxes) to apply, for example, Hide action, within 1 method for all objects without specifying hiding for each? Like private void(List<objects>,action)

2 Answers2

2

Since all controls inherit from the same base class (i.e. Control), you can do this with a generic method and passing in an Action. For example:

public void ApplyToAll<T>(IEnumerable<T> items, Action<T> action)
{
    foreach (var item in items)
    {
        action(item);
    }
}

And call the method like this:

var items = new List<Control> { lblHum, lblCo2... etc };

ApplyToAll(items, x => x.Visible = false);
DavidG
  • 113,891
  • 12
  • 217
  • 223
  • For a `List` you can call `ForEach(action)` – Charlieface Jan 19 '21 at 17:06
  • @Charlieface Yes, but I think that's a method that shouldn't exist. – DavidG Jan 19 '21 at 17:08
  • And `ApplyToAll` should? What's the difference, the code is 100% identical? A `List` is not quite the same semantic as `IEnumerable`, it is meant to be mutable, so a justified function IMO. – Charlieface Jan 19 '21 at 19:53
  • @Charlieface ForEach is in the Linq namespace but it kinda goes against everything Linq stands for, which is *querying*. It doesn't return anything so isn't a query. – DavidG Jan 19 '21 at 19:57
  • @Charlieface Linq is meant to be side-effect free by nature, but `ForEach` goes against that philosophy. – DavidG Jan 19 '21 at 20:01
  • I challenge you to find it [System.Linq namespace](https://learn.microsoft.com/en-us/dotnet/api/system.linq?view=net-5.0), it's not there. You will find it here though, [List.ForEach](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1.foreach?view=net-5.0) it's specific to `List` for a reason – Charlieface Jan 19 '21 at 20:04
  • Yes, but it gets lumped in with Linq all the time. See Jon Skeet's opinion [here](https://stackoverflow.com/a/200614/1663001) and Eric Lippert [here](https://learn.microsoft.com/en-us/archive/blogs/ericlippert/foreach-vs-foreach) – DavidG Jan 19 '21 at 20:05
  • They are both discussing why not to have it *in LINQ specifically*, they don't mention it being lumped with LINQ nor do they demonize `List.ForEach` @JonSkeet can you confirm maybe? – Charlieface Jan 19 '21 at 20:09
2

You can write something like this:

public void HideAll(params Control[] controls)
{
     foreach(var control in controls) control.Hide();
}

Call it like this:

HideAll(lblHum, lblCo2,  etc);

Or for something more flexible:

public void GroupAction(Action<Control> action, params Control[] controls)
{
    foreach(var control in controls) action(control);
}

And then call it like this:

GroupAction(c => c.Hide(), lblHum, lblCo2,  etc);

In both cases, though, the collection is still there. You just hid it with a method. And since the method is fairly simple, I'm not sure you get much value above putting the collection directly in your code. That is, you can make a list as a member of the form class and add the controls when the form is initialized. Then you can loop over the list whenever you want.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794