Question Help. Can't assign an array of images to an ImageList.

Mugsy

Member
Joined
Sep 30, 2020
Messages
16
Programming Experience
10+
I'm trying to sort images before assigning them to an ImageList object.

Using a "For... Each" loop, I can assign images one at a time as they are read directly from the computer.

The problem is, this method reads the files alphabetically, so it reads "image09.png", "image10.png", "image100.png", "image101.png", "image102.png", etc before "image11.png" (physically renumbering the users files is not an option.)

My "solution" was to read the images into an array of type Image, inserting images into the array in order, then assign that array to my "ImageList" object.

This results in an assignment error, and I have no idea why. :cry:

Can't assign image array to an ImageList (error on line 11):
Dim imgImageArray(200) As Image
...
For Each ClosetFile As String In IO.Directory.GetFiles(strClosetPath, strCategory & "*.png", SortOrder.Ascending)
...
       Dim img = Image.FromFile(ClosetFile)
       imgImageArray(intPosition) = img ' "intPosition" parsed from filename.
...
Next ' ending For/Each loop.

For intCnt = 1 To intTotalNumberOfFiles ' Load image array with sorted list.
    ImageList2.Images.Add(imgImageArray(intCnt))
    ' also tried: ".AddRange" w/o the loop.
Next

Is there any other way to assign images to an ImageList control other than directly from disk?

TIA
 
Last edited:
terminology is important in programming so I have some corrections.

ImageList is not a control. It is a component, which is all that's required for use in the designer. A control is a class that inherits Control, which Imagelist does not. That's why it's in the Components section of the Toolbox.

You don't assign anything to an object. You assign objects to variables or properties. you might assign an object to a list item or array element or you might add an object to a list.
 
With regards to sorting your file paths, there is a Windows API function that you can use to sort the same way that Windows does in File Explorer. The first step is to declare the unmanaged function:
VB.NET:
Imports System.Runtime.InteropServices

Public Module NativeMethods

    <DllImport("shlwapi.dll", CharSet:=CharSet.Unicode)>
    Public Function StrCmpLogicalW(x As String, y As String) As Integer
    End Function

End Module
You can then use that method in a number of ways. If it's a one-off sort of an array, the simplest option is to use the overload of Array.Sort that takes a Comparison(Of T) delegate as an argument:
VB.NET:
Dim filePaths = Directory.GetFiles(strClosetPath, strCategory & "*.png")

Array.Sort(filePaths, AddressOf NativeMethods.StrCmpLogicalW)
You can then check the contents of that array and you'll see that it is sorted alphanumerically, just as File Explorer does.
 
As for the issue, you can't set an item in the ImageList that doesn't already exist. If the list is initially empty, you need to Add images to it. You should ALWAYS prefer calling AddRange once to calling Add multiple times. Only do the latter if there will be a break between the Add calls. In this case, you can create all the Image objects first and then add them all in a single batch. There are a number of variations in ways to create the Images. You could use a loop:
VB.NET:
Dim upperBound = filePaths.GetUpperBound(0)
Dim images(upperBound) As Image

For i = 0 To upperBound
    images(i) = Image.FromFile(filePaths(i))
Next
The simplest option is to use LINQ though:
VB.NET:
Dim images = filePaths.Select(Function(s) Image.FromFile(s)).ToArray()
Either way, once you have an Image array, you simply pass it to AddRange:
VB.NET:
ImageList2.Images.AddRange(images)
I'm not sure why your original code didn't work. At a glance it seems that it should but, given that you would have been given an error message as a diagnostic aid, you should have given that to us, so that we know what we're looking for. Regardless, this code is tested and works. Just note that, because you are calling Image.FromFile, all the files will be locked. If you're going to be done with those Image objects before the application closes, be sure to call Dispose on each one, so as to release the files.
 
As for the issue, you can't set an item in the ImageList that doesn't already exist. If the list is initially empty, you need to Add images to it. You should ALWAYS prefer calling AddRange once to calling Add multiple times. Only do the latter if there will be a break between the Add calls. In this case, you can create all the Image objects first and then add them all in a single batch. There are a number of variations in ways to create the Images. You could use a loop:
VB.NET:
Dim upperBound = filePaths.GetUpperBound(0)
Dim images(upperBound) As Image

For i = 0 To upperBound
    images(i) = Image.FromFile(filePaths(i))
Next
The simplest option is to use LINQ though:
VB.NET:
Dim images = filePaths.Select(Function(s) Image.FromFile(s)).ToArray()
Either way, once you have an Image array, you simply pass it to AddRange:
VB.NET:
ImageList2.Images.AddRange(images)
I'm not sure why your original code didn't work. At a glance it seems that it should but, given that you would have been given an error message as a diagnostic aid, you should have given that to us, so that we know what we're looking for. Regardless, this code is tested and works. Just note that, because you are calling Image.FromFile, all the files will be locked. If you're going to be done with those Image objects before the application closes, be sure to call Dispose on each one, so as to release the files.

Thx. I'll give this a try this afternoon (busy day.)

The error (as noted in my question) was a simple "assignment error". No more detail given in the runtime error message.
 
There's no need to quote a whole post just to say "thanks, will do". There was no point to quoting that post at all. You're just making the thread harder to follow. You only need to quote something if there's a specific reason to single that part out to make it clear that that's what you're referring to. If I'm the only one who's replied and your responding to the post as a whole then there's nothing to single out so no point quoting.
 
The error (as noted in my question) was a simple "assignment error". No more detail given in the runtime error message.
There's no way that's true. There would have been an actual error message. They are provided for a reason.
 
(Sorry for the late reply. Death in the family.)

I always have difficulty implementing "<DllImport(..." statements. They're always redlined when I include the code (added to a module in this case).

I can't add/test the remaining code till I straighten that out.

TIA.
 
If they are underlined in red then there's a compilation error, which means there's an error message, which tells you what the problem is. Perhaps you could have posted that error message and we could have already solved the problem for you. The code I posted has been tried and tested so all you had to do was copy and paste it. My guess would be that you haven't imported the appropriate namespace but I can only guess at this point.
 
If they are underlined in red then there's a compilation error, which means there's an error message, which tells you what the problem is. Perhaps you could have posted that error message and we could have already solved the problem for you. The code I posted has been tried and tested so all you had to do was copy and paste it. My guess would be that you haven't imported the appropriate namespace but I can only guess at this point.

My apologies, but I have since made significant changes to the code, so that particular error is gone so I can't reproduce it.
At the time, that particular bit of code was not underlined in red (or else the program never would have run & given me a runtime error.)

After making changes, I'm still back to my original problem of not being able to assign anything to my "ImageList" other than loading the images directly into it from disk.
 
Back
Top