1

I'm still in the beginning stage of learning c#, so i have a question about a part of my code. I strongly have the feeling there should be a way smarter way to accomplish what i try to do:

So what do i have: A WPF window, with a whole bunch of images on it. At the start, i want them all to be set to Hidden, so at the initialize part of the window, i set them all hidden and do it like this:

.....
IMx01y01W.Visibility = Visibility.Hidden; 
IMx23y73W.Visibility = Visibility.Hidden;
IMx31y21W.Visibility = Visibility.Hidden;
IMx03y16W.Visibility = Visibility.Hidden;
.....

There is a logical in the names of the images like IMx##y##W, where the ## are the variable numbers.

As stated above, i strongly have the feeling that there should really be some smarter way to do this.

=======

EDIT 1

Ok so far i ended up with this:

    foreach (object obj in LogicalTreeHelper.GetChildren(this))
    {
        if (obj is Image)
        {
        Image obj = (Image)item;
        obj.Visibility = Visibility.Hidden;
        }

    //do something
    }

The part in the if statement is totally wrong, but i don't know how to go on on this point. can anyone push me a bit more in the right direction ? thanx!

Dante1986
  • 58,291
  • 13
  • 39
  • 54
  • You can cycle through all the "chidren" controls in your window with [LogicalTreeHelper.GetChildren](http://msdn.microsoft.com/en-us/library/ms598654.aspx) – Paolo Falabella Jan 13 '12 at 19:21
  • Please don't prefix your titles with things like "c# (learning) ". That's what we use tags for on [so]. – John Saunders Jan 13 '12 at 19:27
  • Ok, wont do that again in the future :) – Dante1986 Jan 13 '12 at 19:36
  • @Dante1986 : Your edit contains a simple syntax error. You can't have two variables named obj in the same scope. See my edited answer below. (You basically just have the obj and item variables reversed.) – Paul Sasik Jan 13 '12 at 19:40

3 Answers3

2

You can frame this requirement as "set the Visibility property of the various images to the same value", i.e. they all show/hide based on the same exact flag. WPF has some mechanisms that require a slightly different mindset than traditional imperative code, but can greatly simplify this scenario.

WPF supports the concept of databinding, which allows you to declare the images' dependency on a value instead of applying the value by hand. You can take advantage of this to manage the Visibility property values solely in markup.

The main thing to learn about is the DataContext property, which represents the object currently bound to a particular control. In this case, you can set the data context to a value of Visibility:

public MainWindow()
{
    DataContext = Visibility.Hidden;
}

Once you do that, it cascades throughout the object tree, so all of the children of MainWindow inherit this same value. This means you can do this in your XAML:

<Image x:Name="IMx01y01W" Visibility="{Binding}" />
<Image x:Name="IMx23y73W" Visibility="{Binding}" />

That tells WPF that you want the Visibility property to reflect the value of the current DataContext, which will be the Visibility.Hidden value you set in the constructor.

The nice part about this is that if you change the value of the DataContext property, it will automatically be reflected in all your images without any extra work:

private void MakeImagesVisible()
{
    DataContext = Visibility.Visible;

    // At this point, all images will be visible
}

The key takeaway is that WPF does things in a different way than traditional UI paradigms such as Windows Forms. Learning the philosophy behind these new techniques, rather than replicating legacy techniques, will help make WPF easier to understand and bend to your will.

Bryan Watts
  • 44,911
  • 16
  • 83
  • 88
  • this way is even nicer i think, thanx you very much for the explanation too, this really helps understanding – Dante1986 Jan 13 '12 at 20:00
  • making them visible will happen later on, but that will be one by one. Just tested this, and it really works exactly as wanted. – Dante1986 Jan 13 '12 at 20:04
1

Yes there is. You can get all children of a container control and filter for a particular type, images in your case, and perform actions on those instances. See this forum post for a sample. And this SO post. And this one.

For EDIT 1:

foreach (object obj in LogicalTreeHelper.GetChildren(this))
{
    if (obj is Image)
    {
    Image img = (Image)obj;
    img.Visibility = Visibility.Hidden;
    }
}
Community
  • 1
  • 1
Paul Sasik
  • 79,492
  • 20
  • 149
  • 189
  • ok, i will see if i can try to understand how this works (as stated, im still new in the c#, but learning fast hehehe) – Dante1986 Jan 13 '12 at 19:26
  • So far, so good, but im again a bit stuck. I edited my post again, maybe you can push me a little bit more in the right way again ? – Dante1986 Jan 13 '12 at 19:37
  • great! thanx again. this works perfect. Just for my understanding of c#: now its done for all images in that window, is there some way i can say like: ..Except the one that is called.....(specific name/Regex) – Dante1986 Jan 13 '12 at 19:44
  • @Dante1986 : Absolutely. Just have another if statement after you assign the img object. Something like: `if (RegEx.IsMatch(img.Name, "your regex expression") ...` By the way, you're stretching way past the original question here. If you have issues, please post another. – Paul Sasik Jan 13 '12 at 19:53
0

One thing that you can do is

IMx01y01W.Visibility = IMx23y73W.Visibility = ... = Visibility.Hidden;

but I wouldn't call this any more readable.

What you could do instead is create a collection of IMx01y01W objects (of their base class) and iterate through that collection settings Visibility to Hidden.

Denis Biondic
  • 7,943
  • 5
  • 48
  • 79