【问题标题】:ListView throwing ArgumentException when form is shown显示表单时 ListView 抛出 ArgumentException
【发布时间】:2019-02-13 09:39:56
【问题描述】:

我正在构建一个ListView 来向用户显示图像。

在表单构造函数中,我加载所有图像,然后显示表单。然后在ShowDialog()函数中抛出一个ArgumentException

消息:参数无效
ParamName:null
InnerException:null
来源:System.Drawing
StackTrace
System.Drawing.Image.get_Width() System.Drawing.Image.get_Size() System.Windows.Forms.ImageList.CreateBitmap(Original original, 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(消息& m) System.Windows.Forms.Control.WndProc(消息& m) System.Windows.Forms.ListView.WndProc(消息& m) System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

我使用solution from here 以便能够在用户需要时删除图像。如果我不使用该解决方案并且不使用 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);
        }
    }
}

我认为奇怪的是,当我从表单的Shown 事件调用LoadImages() 方法时,它工作正常。

所以我并没有真正陷入困境,因为我有一个解决方法,但我很好奇为什么会抛出这个异常。

【问题讨论】:

  • 您是否尝试详细检查异常。特别是什么参数无效?
  • @Ucho 是的,我检查过(更新了我的问题),ParamName 为空...
  • 您是否尝试了解这是否与特定图像有关? IE。过滤使用的文件?
  • lv_Images.LargeImageList.Images.Add(file.Name, (Image)img.Clone());
  • @Jimi 有效。你能解释一下为什么吗?

标签: c# winforms listview


【解决方案1】:

我认为构造函数中正在执行的代码试图找到位图的大小,正如您在堆栈跟踪顶部看到的那样:

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

但是,这是一个问题,因为该表单尚未显示。这可以解释为什么在FormShown() 中它可以完美运行。

【讨论】:

  • 我想到了,但是如果我不使用 using 块,它在构造函数中可以正常工作。
【解决方案2】:

经过几次尝试,我终于明白发生了什么。

如果不克隆 Image,它会被释放并释放文件句柄,但它会变得无法显示,因为 ImageList 丢失了原始源。

根据 Jimi 的 cmets,我可以在 using 块中使用 Image.Clone(),即使我想从代码中删除图像,它也能正常工作。原始图像会被释放,但克隆的图像不会。

但后来我无法从 Windows 资源管理器中删除图像,说另一个进程已经在使用此文件。

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);
        }
    }
}

还是感谢您的提示。

【讨论】:

    猜你喜欢
    • 2012-08-10
    • 2018-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-11
    • 2021-12-01
    • 2010-10-17
    • 2020-10-26
    相关资源
    最近更新 更多