0

I'm struggling using XAML variables in a loop, my problem is detailed below :

I've a foreach() loop, I've 4 images in XAML called let's say image1, image2, image3, image4 now I would like to associate a image that I've got its path in my foreach loop to each image variable. An obvious solution would be :

foreach() {
    //my stuff
    image1.Source = bitmapSource;
    image2.Source = bitmapSource;
    image3.Source = bitmapSource;
    image4.Source = bitmapSource;
}

But this solution is not flexible, I thought about putting my image variables in an array but I don't think that is possible (at least I haven't found anything that goes in this way). What's the best / cleanest way to do it ? Thanks

Clemens
  • 123,504
  • 12
  • 155
  • 268
Steeven_b
  • 747
  • 2
  • 10
  • 22
  • Can the people who dislike it explain or give at least a piece of solution, or some hints ? We are not all senior devs, I'm a student and am still learning.. – Steeven_b Oct 10 '17 at 08:58
  • 3
    Instead of a fixed set of Image controls you should have one in the ItemTemplate of an ItemsControl. Bind the ItemsControl's ItemsSource to a collection of ImageSource objects or image file path strings. See e.g. [this answer](https://stackoverflow.com/a/40024424/1136211) or [this one](https://stackoverflow.com/a/34557467/1136211). – Clemens Oct 10 '17 at 09:01
  • @Clemens Oh yes, I didn't think about using ItemsControl, I'll go on that way. Thanks. – Steeven_b Oct 10 '17 at 09:04
  • 1
    I didn't downvote, but your question is lacking XAML and without a specific UI example it is to broad in my opinion. (or it might be primarily opinion based since you ask for *"What's the best way"*) – grek40 Oct 10 '17 at 09:15
  • Well I didn't put my xaml code because in my opinion there was nothing there that was necessary to answer, just simple image tags inside different grids such as : ``. When I asked what's the best way it's about common / good practices in C#, in any language there is a better way /cleaner to do something.For example if you want to loop through a list in C#, in most cases `foreach()` is a better way than `for()` or `while()`. – Steeven_b Oct 10 '17 at 09:18
  • 1
    I haven't downvoted but the question isn't great... A few questions I have looking at it: What is bitmapSource? Do you really want to set all four images to the same thing? What are you actually looping over and what are you doing with the items you are getting from the foreach? – Chris Oct 10 '17 at 09:24
  • *"in most cases foreach() is a **better way** than for() or while()"* = wrong. As for question, loop through controls should have been bringing you [there](https://stackoverflow.com/q/974598/1997232), no? As a simple workaround put those controls into *temprorary* array: `for(var image in new[] {image1, image2, ...}) ...` – Sinatr Oct 10 '17 at 09:25
  • In the foreach I'm looping through a list that contains paths of TIF images, then inside the foreach I convert them to `bitmapSource`, but I still believe that it wasn't needed to know that to answer. I just don't want to "pullute" my post with useless informations and focus only on what is important for someone to be able to answer. – Steeven_b Oct 10 '17 at 09:27
  • @SteevenBrunner I'm really wondering did you ever look at my answer below ?? Don't consider the downvotes so much because a lot of them given with no reason. – Salah Akbari Oct 10 '17 at 09:29
  • @Sinatr I'm kind of begginer in C#, could you explain why foreach() wouldn't be better than for() and while() to loop through a list. Coming from C and C++, in my head foreach is just THE tool to do it. But as a beginner I'm probably wrong, that's why I would like you to explain this point. Thanks. – Steeven_b Oct 10 '17 at 09:30
  • @S.Akbari Yes of course I did, but I think that the answer of Clemens is better in my case even though yours might works as well. – Steeven_b Oct 10 '17 at 09:31
  • @SteevenBrunner The linked answer introduce a complete different way of doing your work. Although it might be quit correct and right approach but it has nothing to do with your current question which is *Flexible loop through variables*! – Salah Akbari Oct 10 '17 at 09:33
  • @S.Akbari Well each image is in a different grid in my case, your solution should works for images that are inside the same container right ? – Steeven_b Oct 10 '17 at 09:36
  • @SteevenBrunner Well you can place that different grids inside another container and then loop through that main container by helping `VisualTreeHelper`. Although you didn't mention that you have your images in different containers at first. – Salah Akbari Oct 10 '17 at 09:43
  • @SteevenBrunner Check my updated answer for images that are inside different containers. – Salah Akbari Oct 10 '17 at 09:48
  • I'll try out both yours and Clemens answers, the best way to learn is to try and get more knowledge. – Steeven_b Oct 10 '17 at 09:51
  • @SteevenBrunner *"Well I didn't put my xaml code because in my opinion there was nothing there that was necessary to answer, just simple image tags inside different grids"* - thats exactly why it is necessary to see the XAML! It is a huge difference to a potential answer, whether one container contains all images or the are spread across the UI in some non-uniform way with different containers involved and it's also important to know whether the UI structure contains other image elements that should NOT receive the same image source. (Now I really downvoted because you had time to clarify) – grek40 Oct 10 '17 at 10:57

1 Answers1

1

Use LINQ and Enumerable.OfType<TResult> Method:

Grid1.Children.OfType<Image>().ToList().ForEach(c => c.Source = bitmapSource);

I've presumed the images are inside the Grid container with name Grid1. Change accordingly if they are inside another container.

EDIT: If your images are inside different containers as you pointed out in your last comment you can do this:

public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) 
    where T : DependencyObject
{
    if (depObj != null)
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
            if (child is T)
            {
                yield return (T)child;
            }

            foreach (T childOfChild in FindVisualChildren<T>(child))
            {
                yield return childOfChild;
            }
        }
    }
}

And then:

FindVisualChildren<Image>(MainGrid).ToList().ForEach(c => c.Source = bitmapSource);

Again I've presumed your different containers are inside a main Grid with name MainGrid.

Salah Akbari
  • 39,330
  • 10
  • 79
  • 109