Joost H.
Joost H.

Reputation: 13

Multiple images from folder

as I'm fairly new to C# and WPF I just can't figure out how to do this. I have a form that should show 151 images (all pokemon generation 1 sprites) in a form. The way I've done it now is that it shows the same image 151 times instead of all images just once. The code I wrote for this is as follow:

    public partial class PokeGame : Window
{
    BitmapImage carBitmap = new BitmapImage(new Uri("pack://application:,,,/Images/All_Sprites/001.png", UriKind.Absolute));

    {

        InitializeComponent();

        int imgCount = 151;
        int left = 0;
        int top = 0;
        List<Image> imageList = new List<Image>();
        for (int i = 0; i < imgCount; i++)
        {
            if(i % 10 == 0)
            {
                if (i != 0)
                {
                    top += 175;
                    left = 0;
                } else
                {
                    top = 0;
                    left = 0;
                }
            }

            Image img_ding = new Image();
            img_ding.Source = carBitmap;
            img_ding.Height = 150;
            img_ding.Width = 150;
            img_ding.Margin = new Thickness(left, top ,0 ,0);
            imageList.Add(img_ding);
            left += 175;
        }

        int j = 0;

        foreach (Image img in imageList)
        {
            imageCanvas.Children.Add(img);
            j++;
        }

    }

As you can see there's probably lots of room for improvement in my code. However, my question is: How can I make it so that it doesn't display the same image 151 times but all images (sprite001.png, sprite002.png, sprite003.png, etc.)?

Upvotes: 1

Views: 1457

Answers (3)

Clemens
Clemens

Reputation: 128146

Instead of programmatically adding Image controls to a Canvas, write this XAML:

<ItemsControl x:Name="images">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Columns="10"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Image Width="150" Height="150" Source="{Binding}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Probably add some Margin to the Image control in the DataTemplate.

In code behind, add one line to the constructor of your MainWindow:

using System.Linq;
...

public MainWindow()
{
    InitializeComponent();

    images.ItemsSource = Enumerable
        .Range(1, 151)
        .Select(i => string.Format("pack://application:,,,/Images/{0:000}.png", i));
}

Now you might want to create a proper view model, where you would have a collection-type property for your images, like

public class ViewModel
{
    public ObservableCollection<string> Images { get; }
        = new ObservableCollection<string>(Enumerable
            .Range(1, 151)
            .Select(i => string.Format("pack://application:,,,/Images/{0:000}.png", i)));
}

You would then assign the Window's DataContext to an instance of the view model, and bind to the collection property like this:

public MainWindow()
{
    InitializeComponent();
    DataContext = new ViewModel();
}

XAML

<ItemsControl ItemsSource="{Binding Images}">
    ...
</ItemsControl>

Upvotes: 5

You create carBitmap exactly once, outside the loop, and use it every time. Create a new one for each image instead.

        Image img_ding = new Image();
        BitmapImage carBitmap = new BitmapImage(new Uri("pack://application:,,,/Images/All_Sprites/001.png", UriKind.Absolute));
        img_ding.Source = carBitmap;

I assume that path ending in 001.jpg should be changing each time; no doubt you can figure that out. Is it the value of i in the for loop, stringified and left-padded with zeroes? That'd look like this:

        Image img_ding = new Image();
        var uri = String.Format("pack://application:,,,/Images/All_Sprites/{0:000}.png", i);
        //  N.B. UriKind.Absolute is redundant, sigh
        BitmapImage carBitmap = new BitmapImage(new Uri(uri, UriKind.Absolute ));
        img_ding.Source = carBitmap;

Also, @Clemens is going to provide an answer that shows you how to rewrite the whole thing using an ItemsControl, which will be much nicer than this. I already wrote somebody a bunch of XAML this morning so it's his turn.

Upvotes: 4

Darren Wainwright
Darren Wainwright

Reputation: 30747

You need to define your bitmap inside the loop, not outside. Then each iteration will create a new bitmap with the new path.

so something like:

for (int i = 0; i < imgCount; i++)
{
   // padding left will give you 001 and 010 and 151
   string img = i.ToString().PadLeft(3, '0');
   BitmapImage carBitmap = new BitmapImage(new Uri("pack://application:,,,/Images/All_Sprites/" + img+".png", UriKind.Absolute));
   // the rest of your code
}

Upvotes: 0

Related Questions