ListView выбрасывает ArgumentException при отображении формы - PullRequest
0 голосов
/ 13 февраля 2019

Я строю ListView для отображения изображений пользователю.

В конструкторе формы я загружаю все изображения, после чего форма отображается.Затем в функцию ShowDialog() добавляется ArgumentException:

Сообщение : параметр недействителен
ParamName : null
InnerException : ноль
Источник : System.Drawing
StackTrace :
System.Drawing.Image.get_Width () System.Drawing.Image.get_Size () System.Windows.Forms.ImageList.CreateBitmap (Оригинальный оригинал, Boolean & ownsBitmap) System.Windows.Forms.ImageList.CreateHandle () System.Windows.Forms.ImageList.get_Handle () System.Windows.Forms.ListView.RealizeProperties () System.Windows.Forms.ListView.OnHandleCreated (EventArgs e) System.Windows.Forms.Control.WmCreate (Message & m) System.Windows.Forms.Control.WndProc (Message & m) System.Windows.Forms.ListView.WndProc (Message & m) System.Windows.Forms.NativeWindow.DebuggableCallback (IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

Я использую решение отсюда чтобы иметь возможность удалять изображения, когда этого требует пользователь.Если я не использую решение и не использую блок using, он работает нормально.Однако я больше не смогу удалять изображения.

Вот мой код.Обратите внимание, что метод всегда выполняется до конца (я проверял это, используя точки останова).Исключение выдается только тогда, когда я вызываю ShowDialog():

private void LoadImages()
{
    lv_Images.LargeImageList = new ImageList();
    lv_Images.LargeImageList.ImageSize = new Size(64, 64);
    DirectoryInfo di = new DirectoryInfo(initialDirectory);
    foreach (FileInfo file in di.EnumerateFiles())
    {
        if (isImage(file)) //Simply checks the file extension
        {
            using (Image img = Image.FromFile(file.FullName))
            {
                lv_Images.LargeImageList.Images.Add(file.Name, img);
            }
            int index = lv_Images.LargeImageList.Images.IndexOfKey(file.Name);
            lv_Images.Items.Add(file.Name, file.Name, index);
        }
    }
}

Что мне кажется странным, так это то, что он работает нормально, когда я вызываю метод LoadImages() из события Shown формы.

Так что я на самом деле не застрял, поскольку у меня есть обходной путь, но мне любопытно, почему выбрасывается это исключение.

Ответы [ 2 ]

0 голосов
/ 14 февраля 2019

После нескольких испытаний мне, наконец, удалось понять, что происходит.

Без клонирования изображения оно было бы удалено и дескриптор файла был освобожден, но его стало бы невозможно отобразить, потому что ImageListпотерял первоначальный источник.

Согласно комментариям Джими, я мог использовать Image.Clone() в своем блоке использования, и это работало, даже если я хочу удалить изображение из своего кода.Исходное изображение будет удалено, но клонированное не будет.

Но тогда я не смог удалить изображение из Windows Explorer, сказав, что этот процесс уже используется другим процессом.

Image.Clone(), очевидно, сохраняет дескриптор исходного файла и не сохраняет его внутри.

Поэтому я использовал MemoryStream для копирования содержимого файла изображения, и мое изображение имеет дескриптор на MemoryStream.Теперь я могу удалять изображения по своему усмотрению, и еще проще написать:

private void LoadImages()
{
    lv_Images.LargeImageList = new ImageList();
    lv_Images.LargeImageList.ImageSize = new Size(64, 64);
    DirectoryInfo di = new DirectoryInfo(initialDirectory);
    foreach (FileInfo file in di.EnumerateFiles())
    {
        if (isImage(file)) //Simply checks the file extension
        {
            //File.ReadAllBytes will release the handle when the byte array is constructed.
            lv_Images.LargeImageList.Images.Add(file.Name, Image.FromStream(new MemoryStream(File.ReadAllBytes(file.FullName))));
            int index = lv_Images.LargeImageList.Images.IndexOfKey(file.Name);
            lv_Images.Items.Add(file.Name, file.Name, index);
        }
    }
}

Спасибо за ваши советы в любом случае.

0 голосов
/ 13 февраля 2019

Я думаю, что код, выполняемый в конструкторе, пытается найти размер растрового изображения, как вы можете видеть в верхней части трассировки стека:

System.Drawing.Image.get_Width() System.Drawing.Image.get_Size() 
System.Windows.Forms.ImageList.CreateBitmap(Original original, Boolean& ownsBitmap) 

Это проблема, однако,потому что форма еще не была показана.Это объясняет, почему в FormShown() он работает безупречно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...